求二分图最大匹配(指派问题)的匈牙利算法:
谈匈牙利算法自然避不开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;
来自:http://www.csdn.net/develop/Article/19/19501.shtm
二分图的最大匹配匈牙利算法
#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).
来自:http://topic.csdn.net/u/20080928/14/4e7a079c-21c4-484b-ab80-3785beccd489.htm