1. 程式人生 > >最大匹配 人員分配[鄰接矩陣]

最大匹配 人員分配[鄰接矩陣]

Description

設有M個工人x1, x2, …, xm,和N項工作y1, y2, …, yn,規定每個工人至多做一項工作,而每項工作至多分配一名工人去做。由於種種原因,每個工人只能勝任其中的一項或幾項工作。問應怎樣分配才能使盡可能多的工人分配到他勝任的工作。這個問題稱為人員分配問題。

Input

第一行兩個整數m,n分別為工人數和工作數。
接下來一個整數s,為二分圖的邊數。
接下來s行,每行兩個數ai,bi表示第ai個工人能勝任第bi份工作

Output

一個整數,表示最多能讓多少個工人派到自己的勝任的工作上。

Sample Input

3 3
4
1 2
2 1
3 3
1 3
Sample Output

3
Hint

規模:
1<=m,n<=100
1<=s<=10000
.
.
.
.
.
分析
人員分配問題可以用圖的語言來表述。令X={x1, x2, …, xm},Y={y1, y2, …,yn},構造二分圖G=(X, Y, E)如下:

在這裡插入圖片描述
對於1≤i≤m,1≤j≤n,當且僅當工人xi勝任工作yi時,G中有一條邊xiyi,

於是人員分配問題就成為在G中求一個最大匹配的問題。

為了簡單起見,假設工人數等於工作數,即N=M,且N≤100,這裡,N也可以看作是二分圖的|X|和|Y|。
.
.
.
.
.
程式:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
bool f[201][201],bz[300];
int a[300];
int n,m,s;

bool find(int x)
{
	for (int i=1;i<=m;i++)
		if (f[x][i]&&!bz[i])
		{
			bz[i]=true;
			int w=a[i];
			a[i]=x;
			if (w==0||find(w)) return true;
			a[i]=w;
		}
	return false;
}

int main()
{
	scanf("%d%d",&n,&m);
	scanf("%d",&s);
	memset(f,false,sizeof(f));
	for (int i=1;i<=s;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		f[x][y]=true;
	}
	for (int i=1;i<=n;i++)
	{
		memset(bz,false,sizeof(bz));
		find(i);
	}
	int ans=0;
	for (int i=1;i<=m;i++)
		if (a[i]!=0) ans++;
	printf("%d",ans);
}