poj1469【模板】【二分圖最大匹配】

題意

一共有N個學生跟P門課程,一個學生可以任意選一門或多門課,問是否達成:
1.每個學生代表的都是不同的課(如果一個學生選修的那門課,那麼他就可以代表這門課)
2.每門課都有一個代表
輸入爲:
P N(課程數跟學生數)
接着有P行,格式爲Count studenti studenti+1 ……studentcount
(Count表示對課程1感興趣的學生數,接着有Count個學生)
如第一行2 1 2表示學生1跟學生2對課程1感興趣
輸出爲:
若每門課都能找到一位代表則輸出”YES”,否則爲”NO”

匈牙利算法

增廣路

增廣路(也稱增廣軌或交錯路): 若P是圖G中一條連通兩個未匹配頂點的路徑,並且屬M的邊和不屬M的邊(即匹配邊和非匹配邊)在P上交替出現,則稱P爲相對於M的一條增廣路徑。
在這裏插入圖片描述
在圖中,紅邊爲三條邊的匹配。路徑x4→y3→x2→y1→x1→y2是一條交錯路

由增廣路的定義可以推出下述三個結論:
(1).P的路徑長度必定爲奇數,第一條邊和最後一條邊都不屬於M,因爲兩個端點分屬兩個集合,且未匹配。
(2).P經過取反操作可以得到一個更大的匹配M’。
(3).M爲G的最大匹配當且僅當不存在相對於M的增廣路徑。

找最大匹配的匈牙利算法流程

假如我們用xM數組表示左邊節點對其右邊節點的匹配,
yM表示右邊節點對其左邊節點的匹配,初始化爲-1;
首先我們先看節點1,尋找下一條邊,假設找到節點5,因爲1跟5都還沒匹配,所以找到一個匹配.標記,xM[1]=5,yM[5]=1;
現在重點看節點3,當尋找下一條邊時,如圖中的藍邊,我們發現節點6的yM[6]=2;已經匹配了.
此時我們就轉到節點6的匹配點2上去,發現節點2的另一條邊2->5中節點5也已經匹配了,yM[5]=1;繼續轉到節點1,發現節點1的邊1->4中節點4還沒匹配.於是我們找到了一個增廣路徑
在這裏插入圖片描述
在這裏插入圖片描述

算法流程

所以流程就是:
1,對於一個未匹配的節點u,尋找它的每條邊,如果它的邊上的另一個節點v還沒匹配則表明找到了一個匹配,直接轉步驟4;
2,假如節點u它邊上的另一個節點v已經匹配,那麼就轉向跟v匹配的節點,假設是w,然後再對w重複1,2的步驟,即尋找增廣路.
3,假如我們在1,2步過程中找到一條增廣路, 那麼修改各自對應的匹配點,轉步驟4,若無增廣路, 則退出.
4,匹配數+1;
在這裏插入圖片描述

本題參考代碼

#include<iostream>
#include<vector>
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
#define in rad()
inline int rad(){
	int x=0,f=1;char c=getchar();while(c>'9'||c<'0')c=getchar();
	if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-48,c=getchar();
	return x*f;
}
const int maxn=3e2+10;
int n,p;
int mp[maxn][maxn],vis[maxn],match[maxn];
int find(int x){
	for(int i=1;i<=n;i++){
		if(mp[x][i] && !vis[i]){
			vis[i]=1;
			if(match[i]==-1 || find(match[i])){
				match[i]=x;
				return 1;
			}
		}
	}
	return 0;
}
int km(){
	int ret=0;
	memset(match,-1,sizeof(match));
	for(int i=1;i<=n;i++){
		memset(vis,0,sizeof(vis));
		ret+=find(i);
	}
	return ret;
}
int main(){
	int t=in;
	while(t--){
		memset(mp,0,sizeof(mp));
		p=in;n=in;
		for(int i=1;i<=p;i++){
			int x=in;
			while(x--){
				int y=in;
				mp[i][y]=1;
			}
		}
		int ans=km();
		if(ans==p)puts("YES");else puts("NO");
	}
	
	return 0;
}



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