[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;
}





posted @ 2012-03-18 21:43  ustc-acm  阅读(217)  评论(0编辑  收藏  举报