第一次看到以为是连通块,结果后来才知道是二分匹配
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4185
通过这个题学习的匈牙利算法。
思路:1、将图输入,并把每个“#”标上序号;
2、将能匹配的进行标记;
3、进行匹配,找出结果;
代码如下:
#include<stdio.h> #include<vector> #include<string.h> #include<algorithm> using namespace std; char a[605][605]; int mapp[605][605]; int pp[700]; int pp1[700]; int mark[605][605]; int vis[700]; int num; int ans; bool find_pp(int x) { for(int j=1; j<=num; j++) { if(mapp[x][j]&&!vis[j])//如果想和j可以匹配而且j没有匹配 { vis[j]=1; if(!pp[j]||find_pp(pp[j])==true)//如果没有匹配 或者 已经匹配了但是找到一个新的匹配,则进行匹配 { pp[j]=x;把x匹配给j return true; } } } return false; } int main() { int t; scanf("%d",&t); int cases=0; while(t--) { int ans=0; cases++; int n; num=1; memset(mapp,0,sizeof(mapp)); memset(mark,0,sizeof(mark)); scanf("%d",&n); for(int i=0; i<n; i++) scanf("%s",a[i]); for(int i=0; i<n; i++) for(int j=0; j<n; j++) { if(a[i][j]=='#') { mark[i][j]=num; num++; } } for(int i=0; i<n; i++) for(int j=0; j<n; j++) { if(a[i][j]=='#') { if(j<n-1&&a[i][j+1]=='#') { mapp[mark[i][j+1]][mark[i][j]]=1; mapp[mark[i][j]][mark[i][j+1]]=1; } if(i<n-1&&a[i+1][j]=='#') { mapp[mark[i][j]][mark[i+1][j]]=1; mapp[mark[i+1][j]][mark[i][j]]=1; } } } ans=0; memset(pp,0,sizeof(pp)); for(int i=1; i<=num; i++)//对每个数字进行匹配 { memset(vis,0,sizeof(vis)); if(find_pp(i)==true) ans++; } printf("Case %d: %d\n",cases,ans/2);//因为是无向图,匹配了两遍,所以结果要除2; } }
时间: 2024-10-16 07:45:59