标签:iostream char while int 建图 getchar ons field cst
题目:http://poj.org/problem?id=2226
巧妙建图:以行或列上的联通块作为点,每个泥格子作为边,求最小点覆盖就可以了!
于是用匈牙利算法找最大匹配。注意要对右部点记录每一个左部点的vis!
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int n=55,N=((n*n)<<1); int r,c,head[N],xnt=1,stack[n],top,cnt,col[n][n],pre[N],knt; char ch[n][n]; bool vis[N]; struct Edge{ int next,to; Edge(int n=0,int t=0,int c=0):next(n),to(t) {} }edge[N]; bool check(int cur) { for(int i=head[cur],v;i;i=edge[i].next) if(!vis[v=edge[i].to]) { vis[v]=1; if(!pre[v=edge[i].to]||check(pre[v])) {pre[v]=cur;/*printf("cur=%d v=%d\n",cur,v);*/return true;} } return false; } void cz1(int i) { cnt++; while(ch[i][stack[top]]==‘*‘)col[i][stack[top--]]=cnt; } void cz2(int i) { cnt++; while(ch[stack[top]][i]==‘*‘) { edge[++xnt]=Edge(head[col[stack[top]][i]],cnt); // printf("%d %d\n",col[stack[top]][i],cnt); head[col[stack[top--]][i]]=xnt; } } int main() { scanf("%d%d",&r,&c); for(int i=1;i<=r;i++) { getchar(); for(int j=1;j<=c;j++) { scanf("%c",&ch[i][j]); if(ch[i][j]==‘*‘)stack[++top]=j; else if(top)cz1(i); } if(top)cz1(i); top=0; } // for(int i=1;i<=r;i++) // { // for(int j=1;j<=c;j++) // printf("%d",col[i][j]);printf("\n"); // } int lm=cnt; for(int i=1;i<=c;i++) { for(int j=1;j<=r;j++) { if(ch[j][i]==‘*‘)stack[++top]=j; else if(top)cz2(i); } if(top)cz2(i); top=0; } for(int i=1;i<=lm;i++) { memset(vis,0,sizeof vis);//万一同一次踩在同一个未匹配右部点的话 if(check(i))knt++; //右边不会主动匹配左边 ,这个i一定未匹配 } printf("%d",knt); return 0; }
标签:iostream char while int 建图 getchar ons field cst
原文地址:https://www.cnblogs.com/Narh/p/8868489.html