HDU2422 The Accomodation of Students

 http://acm.hdu.edu.cn/showproblem.php?pid=2444

有些人互相認識,但認識不具有傳遞性,比如A認識B,B認識C,不代表A認識C。給出所有認識關係,問能不能分成兩個班,每個班裏的人互相不認識。如果可以,一間宿舍可以住兩個人,這兩個人必須互相認識,問最多分配多少宿舍。

二分圖判斷和最大匹配。

分成不同的班相當於能不能構成二分圖,分宿舍就是最大匹配。

注意能構成二分圖不代表最大匹配是n/2。(n爲點的個數)

關於二分圖判斷和最匹配的講解在我的另一篇博客。

#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#define INF 0x3f3f3f3f
#define me(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N=210;
int n,m,line[N][N],ans[N],color[N];
bool used[N];
bool dfs(int u,int c)
{
	color[u]=c;
	for(int i=1;i<=n;i++)
	{
		if(!line[u][i])
			continue;
		if(!color[i])
		{
			if(dfs(i,-c))
				continue;
			return false;
		}
		else
			if(color[i]+color[u])//相同顏色說明不能構成二分圖
				return false;//不同顏色就是一個-1,一個1,相加爲0,爲假,所以不會執行下面的return 
	}
	return true;
}
bool find(int x)
{
	for(int i=1;i<=n;i++)
		if(line[x][i]&&!used[i])
		{
			used[i]=1;
			if(!ans[i]||find(ans[i]))
			{
				ans[i]=x;
				return 1;
			}
		}
	return 0;	
} 
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		me(line,0);
		for(int i=0;i<m;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			line[u][v]=1;//如果在這裏建雙向邊,那麼cnt即最大匹配會是兩倍,匹配裏的每一條邊被算了兩邊 
		}
		me(color,0);
		bool f=1;
		for(int i=1;i<=n&&f;i++)
		{
			if(!color[i]&&!dfs(i,1))
				f=0;
		}
		if(!f)
			printf("No\n");
		else
		{
			me(ans,0);//別忘在這裏初始化 
			int cnt=0;
			for(int i=1;i<=n;i++)
			{
				me(used,0);
				if(color[i]&&find(i))
					cnt++;
			}
			printf("%d\n",cnt);
		}
	}
} 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章