1. 程式人生 > >二分圖的最大匹配匈牙利演算法和最小支配集

二分圖的最大匹配匈牙利演算法和最小支配集

求二分圖最大匹配(指派問題)的匈牙利演算法:  
談匈牙利演算法自然避不開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).