[HDU]2444 The Accomodation of Students
http://acm.hdu.edu.cn/showproblem.php?pid=2444
题意:一堆学生中存在一些互相认识的pair,问能否将这些学生分成两部分,使得每部分中的学生互相都不认识。
先判断是否为二分图,对每对点标记两种颜色。如果出现染色矛盾情况则说明不是二分图,此时需要继续读完输入数据。
是二分图后用最大流完成二分图的最大匹配。
View Code
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define N 205
#define M 1000000
int n,m;
int group[N];//记录点的分组情况
int map[N][N];
void con(int m1)
{
int i,b,c;
for (i=m1+1;i<=m;i++) scanf("%d%d",&b,&c);
}
void init()
{
int i,j;
for (i=1;i<=n;i++) group[i]=0;
for (i=0;i<=n+1;i++)
for (j=0;j<=n+1;j++)
map[i][j]=0;
}
bool divide()
{
int i,b,c;
for (i=1;i<=m;i++)
{
scanf("%d%d",&b,&c);
if (group[b]==0)
{
if (group[c]==0)
{
group[b]=1;
group[c]=2;
map[b][c]=1;
}
else if (group[c]==1)
{
group[b]=2;
map[c][b]=1;
}
else
{
group[b]=1;
map[b][c]=1;
}
}
else if (group[b]==1)
{
if (group[c]==1)
{
con(i);
return false;
}
else
{
group[c]=2;
map[b][c]=1;
}
}
else if (group[b]==2)
{
if (group[c]==2)
{
con(i);
return false;
}
else
{
group[c]=1;
map[c][b]=1;
}
}
}
return true;
}
int ek(int s,int t,int m)//from s to t
{
int ans=0,i;
while (1)
{
int pre[500],p[500],h1=0,h2=0;//pre数组保存路径
h2++;
p[h2]=s;
for (i=0;i<=m;i++) pre[i]=-1;
while (h1<h2)
{
h1++;
int v=p[h1];
for (i=1;i<=m;i++)
if ((map[v][i]>0) && (pre[i]==-1))
{
pre[i]=v;
h2++;
p[h2]=i;
if (i==t) break;
}
if (pre[t]!=-1) break;//找到增广路径
}
if (pre[t]==-1) break;//未找到增广路径
int min=9999999;
for (i=t;i!=s;i=pre[i])
if (map[pre[i]][i]<min) min=map[pre[i]][i];
ans+=min;
for (i=t;i!=s;i=pre[i])//修改残留网络
{
map[pre[i]][i]-=min;
map[i][pre[i]]+=min;
}
}
return ans;
}
int main()
{
//freopen("a","r",stdin);
int i;
while (scanf("%d%d",&n,&m)!=EOF)
{
init();
if (divide()==false)
{
printf("No\n");
continue;
}
else
{
for (i=1;i<=n;i++)
if (group[i]==1) map[0][i]=1;
else if (group[i]==2) map[i][n+1]=1;
cout<<ek(0,n+1,n+2)<<endl;
}
}
return 0;
}