poj3020(二分图的最大匹配)

来源:互联网 发布:数据采集设备检测标准 编辑:程序博客网 时间:2024/05/15 00:41

  典型的二分图最大匹配的问题:

  具体而言就是对里面的点分做两类,一类是横纵坐标之和是奇数的点,一类是横纵坐标之和是偶数点,只有这两类的点才能匹配,建边的原则是看它的四个方向和它本身是否是'*'号,然后答案就是所有为'*'的点减去最大匹配的值。

  

#include "stdio.h"#include "string.h"#include "math.h"#include <string>#include <queue>#include <stack>#include <vector>#include <map>#include <algorithm>#include <iostream>using namespace std;#define MAXM 805#define MAXN 405#define max(a,b) a > b ? a : b#define min(a,b) a < b ? a : b#define abs(a)  a < 0 ? a : (-a)#define Mem(a,b) memset(a,b,sizeof(a))int Mod = 1000000007;double pi = acos(-1.0);double eps = 1e-6;typedef struct{int f,t,w,next;}Edge;Edge edge[MAXM];int head[MAXN];char s[2][MAXN];int kNum;void addEdge(int f, int t, int w){edge[kNum].f = f;edge[kNum].t = t;edge[kNum].w = w;edge[kNum].next = head[f];head[f] = kNum ++;}int T, N, M;int cx[MAXN], cy[MAXN];bool visit[MAXN];int findpath(int u){for(int k = head[u]; k != -1; k = edge[k].next){int t = edge[k].t;if( visit[t] ) continue;visit[t] = true;if( cy[t] == -1 || findpath(cy[t]) ){cy[t] = u;cx[u] = t;return 1;}}return 0;}void solve(){Mem(cx,-1);Mem(cy,-1);Mem(head,-1);kNum = 0;int sum = 0, ans = 0;for(int i = 0; i < N; i ++){getchar();scanf("%s",s[i%2]);for(int j = 0; j < M; j ++){if( s[i%2][j] == '*'){sum ++;if( i - 1 >= 0 && s[(i-1) %2][j] == '*' ){if( ( i + j ) % 2 == 0 ){addEdge( i * M + j, (i-1) * M + j, 0);} else{addEdge( (i - 1) * M + j, i * M + j, 0);}}if( j - 1 >= 0 && s[i%2][j-1] == '*' ){if( ( i + j ) % 2 == 0 ){addEdge( i * M + j, i * M + j - 1, 0);} else{addEdge( i * M + j - 1, i * M + j, 0);}}}}}for(int i = 0; i < N * M; i ++){if( ( i / M + i % M ) % 2 == 0 && head[i] != -1 && cx[i] == -1 ){Mem(visit, false);ans += findpath(i);}}printf("%d\n",sum - ans);}int main(){//freopen("d:\\test.txt", "r", stdin);while(cin>>T){while( T-- ){cin>>N>>M;solve();}}return 0;}

0 0
原创粉丝点击