当前位置: 代码迷 >> 综合 >> POJ 2226 构造二分图 匹配
  详细解决方案

POJ 2226 构造二分图 匹配

热度:1   发布时间:2024-01-20 20:59:19.0

虽然二分图模板已然是十分熟悉,但当初练习的时候也只是搜图论列表一个个的练习模板。

话不多说,分析一下这题的构图。

4 4
*.*.
.***
***.
..*.

给定的4*4的图。

要求我们构造木板。每个点的木板可以有横向和纵向两方选择。题中要求选择最少的木板使全部的点都被盖住。

于是乎,构造图就是构造横向铺的木板和纵向的木板,在图中的当前点选择木板的话,就是横向木板和纵向木板之间有边。

1.构造纵向木板

1.4.

.345

234.

..4.

2构造横向木板

1.2.

.333

444.

..5.

然后 用横向木板和纵向木板构造二分图

对横向木板和纵向木板执行匹配

直接使用匈牙利算法即可。


#include<stdio.h>
#include<iostream>
#include<string.h>
#define MAXN 51
using namespace std;char map[MAXN][MAXN];
int x[MAXN][MAXN];
int y[MAXN][MAXN];
bool ans[MAXN*30][MAXN*30];
bool visited[MAXN*30];
int match[MAXN*30];
int R,C;bool Match( int pre ,int size )
{int i;for( i=1;i<=size;i++ )if( ans[pre][i] && !visited[i] ){visited[i]=true;if( match[i]==-1 || Match( match[i],size ) ){match[i]=pre;return true;}}return false;
}int main()
{while( ~scanf("%d %d",&R,&C ) ){int i,j;for( i=1;i<=R;i++ )scanf( "%s",&map[i][0]+1 );int sign1=1,sign2=1;for( i=1;i<=R;i++ )for( j=1;j<=C;j++ ){if( map[i][j]=='*' ) x[i][j]=sign1;if(  map[i][j]=='*' && map[i][j+1]!='*' )sign1++;}for( j=1;j<=C;j++ )for( i=1;i<=R;i++ ){if( map[i][j]=='*' ) y[i][j]=sign2;if( map[i][j]=='*' && map[i+1][j]!='*' )sign2++;}//printf( "%d %d\n",sign1,sign2 );for( i=1;i<=R;i++ )for( j=1;j<=C;j++ ){if( map[i][j]=='*' )ans[ x[i][j] ][ y[i][j] ]=true;}int res=0;memset( match,-1,sizeof(match) );for( i=1;i<=sign1;i++ ){memset( visited,false,sizeof(visited) );if( Match(i,sign2) )res++;}printf( "%d\n",res );}return 0;
}