1. 程式人生 > >【ACM】杭電OJ 2063

【ACM】杭電OJ 2063

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=2063

借鑑:http://blog.sina.com.cn/s/blog_ac5ed4f30101ewjk.html

二分圖(二部圖):圖論中的一種特殊模型。設G(V,E)是一個無向圖,如果頂點V可以分割成為兩個互不相交的子集(A,B),並且圖中的每一條邊(i,j)所關聯的兩個頂點 i 和 j 分別屬於這兩個不同的頂點集(i in A ,j in B),則稱G是一個二分圖。

最大匹配:給定一個二分圖G,在G的一個子圖M種,M的邊集中任意兩條邊都不依附於同一頂點,則稱M是一個匹配。如果一個匹配中,圖中的每個頂點都和圖中某條邊相關聯,則稱此匹配為完全匹配,也稱作完備匹配。

增廣路(增廣軌或者交錯軌):若P是圖G中一條連通兩個未匹配頂點的路徑,並且屬M的邊和不屬M的邊(即已匹配和待匹配的邊)在P上交替出現,則稱P為相對於M的一條增廣路徑。(來源於二分圖【百度百科】

交替路:從一個未匹配點出發,依次經過非匹配邊,匹配邊,非匹配邊,形成的路徑叫交替路。

增廣路:從一個未匹配點出發,走交替路,如果途徑另一個未匹配點(出發的點不算),則這條交替路稱為增廣路。(來源於:二分圖的最大匹配、完美匹配和匈牙利演算法【部落格園】

初始化:

杭電 <wbr>acm <wbr>2063 <wbr>( <wbr>過山車 <wbr>)


 

0對,無匹配

第一遍  


杭電 <wbr>acm <wbr>2063 <wbr>( <wbr>過山車 <wbr>)

1對, a--A

第二遍
杭電 <wbr>acm <wbr>2063 <wbr>( <wbr>過山車 <wbr>)



杭電 <wbr>acm <wbr>2063 <wbr>( <wbr>過山車 <wbr>)

杭電 <wbr>acm <wbr>2063 <wbr>( <wbr>過山車 <wbr>) 

2對, a--B ,b--A

第三遍
杭電 <wbr>acm <wbr>2063 <wbr>( <wbr>過山車 <wbr>)

杭電 <wbr>acm <wbr>2063 <wbr>( <wbr>過山車 <wbr>)

杭電 <wbr>acm <wbr>2063 <wbr>( <wbr>過山車 <wbr>)

3對, a--B ,b--C ,c--A

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 505;
int map[maxn][maxn];
int vis[maxn];
int pri[maxn];
int K,M,N;

int find(int x)
{
	int i;
	for(i=1;i<=N;i++)
	{
		if(vis[i]==0 && map[x][i])
		{
			vis[i]=1;
			if(pri[i]==-1 || find(pri[i]))
			{
				pri[i]=x;
				return 1;
			}
		}
	}
	return 0;
}

int main ()
{
	int k,j,i,sum;
	while(scanf("%d",&K)!=EOF && K)
	{
		sum=0;
		memset(map,0,sizeof(map));
		memset(pri,-1,sizeof(pri));
		scanf("%d%d",&M,&N);
		for(k=1;k<=K;k++)
		{
			scanf("%d%d",&i,&j);
			map[i][j]=1;
		}
		for(i=1;i<=M;i++)
		{
			memset(vis,0,sizeof(vis));
			if(find(i))
				sum++;
		}
		printf("%d\n",sum);
		/*for(i=1;i<=N;i++)
		{
			printf("%d %d\n",pri[i],i);
		}*/
	}
	return 0;
}

帶註釋的是輸出列印檢視所配對的種類