您的位置:首页 > 其它

hdu 2444 The Accomodation of Students (交叉染色+二分匹配)

2013-11-26 00:27 471 查看
题目链接: hdu 2444

题目大意: 给出N个人和M对关系,表示a和b认识

把N个人分成两组,同组间任意俩人互不认识

若不能分成两组输出No,否则输出两组间俩人互相认识的对数

解题思路: 先判断能否构成二分图,判断二分图用交叉染色法

从某个未染色的点出发把此点染成白色,该点周围的点染成黑色

黑色周围的又染成白色,若走到某个点已经染色

并且它相邻点的颜色与它一样则不是二分图,而是有奇数圈的图

可以这样理解,染白色既加入X集合,黑色既加入Y集合

若某个点即是X集合又是Y集合,那说明不是二分图

判断二分图之后,再求最大的匹配数

PS:二分图是无向图时最大匹配数是Sum/2,因为算多了一倍

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 250
int n,m,pd,sum,edge[MAX][MAX],Map[MAX][MAX],Colors[MAX],cx[MAX],cy[MAX],visit[MAX];

void Color(int u,int color)  //交叉染色判断二分图
{
if(pd==1)
return ;
int i;
for(i=1;i<=n;i++)
{
if(Map[u][i])
{
if(Colors[i]==-1)
{
sum++;
Colors[i]=(!color);
Color(i,!color);
}
else if(i!=u&&Colors[i]==color&&Colors[i]!=-1)
{
pd=1;
return ;
}
}
}
}

int DFS(int u)     //匈牙利最大匹配
{
int i;
for(i=1;i<=n;i++)
{
if(Map[u][i]&&!visit[i])
{
visit[i]=1;
if(!cy[i]||DFS(cy[i]))
{
cy[i]=u;
cx[u]=i;
return 1;
}
}
}
return 0;
}

int main()
{
int i,j,k,a,b;
while(scanf("%d%d",&n,&m)!=EOF)
{
pd=sum=0;
memset(cx,0,sizeof(cx));
memset(cy,0,sizeof(cy));
memset(Map,0,sizeof(Map));
memset(Colors,-1,sizeof(Colors));
memset(visit,0,sizeof(visit));
memset(edge,0,sizeof(edge));
for(i=1;i<=m;i++)     //双向边
{
scanf("%d%d",&a,&b);
Map[a][b]=Map[b][a]=1;
}
Colors[1]=0;
sum=1;
Color(1,0);
if(pd)
printf("No\n");
else
{
for(i=1,sum=0;i<=n;i++)
{
if(!cx[i])
{
memset(visit,0,sizeof(visit));
sum+=DFS(i);
}
}
printf("%d\n",sum/2);   //一半
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: