二分圖的最大匹配匈牙利演算法和最小支配集
求二分圖最大匹配(指派問題)的匈牙利演算法:
談匈牙利演算法自然避不開Hall定理,即是:對於二部圖G,存在一個匹配M,
使得X的所有頂點關於M飽和的充要條件是:對於X的任意一個子集A,和A鄰接的點集為T(A),恆有: |T(A)| > = |A|
匈牙利演算法是基於Hall定理中充分性證明的思想,其基本步驟為:
1.任給初始匹配M;
2.若X已飽和則結束,否則進行第3步;
3.在X中找到一個非飽和頂點x0,作V1 ← {x0}, V2 ← Φ;
4.若T(V1) = V2則因為無法匹配而停止,否則任選一點y ∈T(V1)/V2;
5.若y已飽和則轉6,否則做一條從x0 →y的可增廣道路P,M←M⊕E(P),轉2;
6.由於y已飽和,所以M中有一條邊(y,z),作 V1 ← V1 ∪{z}, V2 ← V2 ∪ {y}, 轉4;
來自:
二分圖的最大匹配匈牙利演算法
#include <fstream.h>
#include <string.h>
#define maxn 105
int nx,ny,jobnum;
int g[maxn][maxn];//鄰接矩陣
int ans;
int sx[maxn],sy[maxn]
int cx[maxn],cy[maxn];//X集v點匹配Y集u點,則有:cx[v]=u,cx[u]=v
int path(int u)
{
sx[u]=1;
int v,i;
for(v=1;v <=ny;v++)
if( (g[u][v]> 0) && (!sy[v]) )
{
sy[v]=1;
if( (!cy[v]) || (path(cy[v])) )
{
cx[u]=v;
cy[v]=u;
return 1;
}
}
return 0;
}
int solve()
{
ans=0;
int i,j;
memset(cx,0,sizeof(cx));
memset(cy,0,sizeof(cy));
for(i=1;i <=nx;i++)
if(!cx[i])
{
memset(sx,0,sizeof(sx));
memset(sy,0,sizeof(sy));
ans+=path(i);
}
return 0;
}
int main()
{
ifstream cin( "1364.in ");
ofstream cout( "1364.out ");
int i,j,k,l;
while(cin> > nx,nx> 0)
{
cin> > ny> > jobnum;
if(cin.fail())
return 0;
memset(g,0,sizeof(g));
for(k=0;k <jobnum;k++)
{
cin> > l> > i> > j;
g[i][j]=1;
}
solve();
cout < <ans < <endl;
}
return 0;
}
最小支配集
頂點集D是圖G=(V,E)的支配集當且僅當對任意u∈V-D存在v∈D使(u,v)∈E.最小支配集問題是對給定圖G找出使|D|最小的支配集D.當所給的圖是一棵樹T時,我們可以利用樹的前序標號表示法設計出求最小支配集D的線性時間演算法如下:
MIN-DOMINATE-SET(T)
begin
for i:=1 to ndo
cover[i]:=0;
D:=;
for i:=ndownto 2 do
if cover[i]=0 then
begin
D:=D∪{parent[i]};
cover[parent[i]]:=1;
cover[parent[parent[i]]]:=1
end
end;{MIN-DOMINATE-SET}
最小支配集問題同樣具有貪心選擇性質和最優子結構性質,從而保證了演算法MIN-DOMINATE-SET的正確性,演算法所需的計算時間也是O(n).