zoj_1654_最大匹配

此题与zoj_1002差不多,但是1002的数据规模很小,直接搜就行,可是此题必须用最大匹配做,对每一个空‘o',对它的左右上下进行遍历,知道碰到墙壁,于是把他所对应的这一块的行标记为二分图的一部分,对应的列标记为另一部分,然后求出最大匹配就是结果,最恶心的是构图,妈的,花了我整整一天的时间才构出来!

#include<iostream> #include<cstdio> #include<memory.h> #include<cstring> using namespace std; #define N 50 #define max 2500 struct node //相互链接的块 { int x_index,y_index; }xy[N][N]; int n,m; //m行n列 int g[max][max]; char s[N][N]; int visit[max]; int pre[max]; int l,r,u,d; //上下左右的标记 int p,q; //二分图,一部分有p个点,另一部分有q个点 void solve() { int i,j,k; p=q=-1; for(i=0;i<m;i++) for(j=0;j<n;j++) xy[i][j].x_index=xy[i][j].y_index=-1; for(i=0;i<m;i++) { for(j=0;j<n;j++) if(s[i][j]=='o') { if(xy[i][j].x_index==-1) { p++; k=j; while(k>=0&&s[i][k]!='#') k--; l=++k; k=j; while(k<n&&s[i][k]!='#') k++; r=--k; for(k=l;k<=r;k++) { xy[i][k].x_index=p; } } if(xy[i][j].y_index==-1) { q++; k=i; while(k>=0&&s[k][j]!='#') k--; u=++k; k=i; while(k<m&&s[k][j]!='#') k++; d=--k; for(k=u;k<=d;k++) { xy[k][j].y_index=q; } } } } memset(g,0,sizeof(g)); for(i=0;i<m;i++) { for(j=0;j<n;j++) if(s[i][j]=='o') g[xy[i][j].x_index][xy[i][j].y_index]=1; } } bool dfs(int start) { int i,temp; for(i=0;i<=q;i++) if(g[start][i]&&!visit[i]) { visit[i]=1; temp=pre[i]; pre[i]=start; if(temp==-1||dfs(temp)) return true; pre[i]=temp; } return false; } int max_match() { int i; memset(pre,int(-1),sizeof(pre)); for(i=0;i<=p;i++) { memset(visit,0,sizeof(visit)); dfs(i); } int ans=0; for(i=0;i<=q;i++) if(pre[i]!=-1) ans++; return ans; } int main() { int t; int i,j; scanf("%d",&t); for(j=1;j<=t;j++) { scanf("%d%d",&m,&n); for(i=0;i<m;i++) { getchar(); scanf("%s",s[i]); } solve(); printf("Case :%d/n%d/n",j,max_match()); } return 0; }  

你可能感兴趣的:(struct)