【题目来源】:https://vjudge.net/problem/HDU-2444
【题意】
给出n个人,描述m组人与人的之间的关系,问,能不能分成两个组,每个组里面的人互相之间不存在对应的关系,若能,求出最大匹配数,不能,输出No。
【思路】
先用染色法判断是否可以分成两组,然后,用二分图匹配匈牙利算法求出最大匹配数。
【代码】
#include<map>
#include<string>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
int n,m;
int relax[210][210];
bool vis[210];
int color[210];
int linked[210];
bool check(int pos,int col)//染色法
{
color[pos]=col;
for(int i=1;i<=n;i++)
{
if(relax[pos][i])
{
if(color[i]!=-1)
{
if(color[i]==col)
{
return 0;
}
}
else if(!check(i,!col))
return 0;
}
}
return 1;
}
bool find(int x)//二分图匹配
{
for(int i=1;i<=n;i++)
{
if(relax[x][i]&&!vis[i])
{
vis[i]=1;
if(!linked[i]||find(linked[i]))
{
linked[i]=x;
vis[i]=0;
return 1;
}
}
}
return 0;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
memset(relax,0,sizeof(relax));
while(m--)
{
int x,y;
scanf("%d%d",&x,&y);
relax[x][y]=relax[y][x]=1;
}
memset(color,-1,sizeof(color));
memset(linked,0,sizeof(linked));
memset(vis,0,sizeof(vis));
if(!check(1,1))
{
printf("No\n");
continue;
}
int ans=0;
for(int i=1;i<=n;i++)
{
if(find(i))
ans++;
}
printf("%d\n",ans/2);
}
}
附加一种暴力(类似染色法)代码:
include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=200+10;
int l[maxn],r[maxn],vis[maxn],pre[maxn];
int mp[maxn][maxn];
int t_x,t_y,n,m;
int dfs(int i)
{
for(int j=1; j<=t_y; j++)
{
int w=r[j];
if(mp[i][w]&&!vis[w])
{
vis[w]=1;
if(pre[w]==-1||dfs(pre[w]))//一个符号打错找了半天bug
{
vis[w]=0;
pre[w]=i;
return 1;
}
}
}
return 0;
}
void init()
{
memset(mp,0,sizeof(mp));
memset(pre,-1,sizeof(pre));
memset(vis,0,sizeof(vis));
for(int i=1; i<=m; i++)
{
int x,y;
scanf("%d%d",&x,&y);
mp[x][y]=1;
mp[y][x]=1;
}
t_x=t_y=0;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
l[++t_x]=1;
for(int i=2; i<=n; i++)
{
int flag=0;
for(int j=1; j<=t_x; j++)
if(mp[i][l[j]])
flag++;
if(flag==0)//条件注意。。
l[++t_x]=i;
else
r[++t_y]=i;
}
bool flag=0;//接下来枚举分好的两个集合里,各自集合里的元素有没有有关系的
for(int i=1; i<=t_x; i++)
{
for(int j=i+1; j<=t_x; j++)
{
if(mp[l[i]][l[j]])
{
flag=1;
break;
}
}
if(flag)
break;
}
for(int i=1; i<=t_y; i++)
{
for(int j=i+1; j<=t_y; j++)
{
if(mp[r[i]][r[j]])
{
flag=1;
break;
}
}
if(flag)
break;
}
if(flag)
{
printf("No\n");
continue;
}
int ret=0;
for(int i=1; i<=t_x; i++)
ret+=dfs(l[i]);
printf("%d\n",ret);
}
}