标签:
第一次看到以为是连通块,结果后来才知道是二分匹配
题目链接: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;
}
}
标签:
原文地址:http://blog.csdn.net/thewaysofar/article/details/51332673