最大二分圖匹配的C++程式碼實現
阿新 • • 發佈:2019-01-06
最大二分圖匹配是典型的圖論問題,一般有兩種做法,一種是運用最大流的思想,不過這種方法效率太低,為O(VE^2),沒有利用好二分圖的特殊性質。另一種做法是匈牙利
演算法,這種方法也是利用了增益路徑的思想,但這種方法充分利用了二分圖的性質,所以效率也是比較高的,為O(VE),而且還能進一步降低,不過我沒有做那種優化,下面就是我
的程式碼:
#include<iostream> #include<queue> #include<vector> #include<stdio.h> using namespace std; class B_Graph { private: struct vertex { bool flag ; //是否被標記 int ver ; //標記的頂點 vector<int>adj; vertex(bool f=0,int v=0):flag(f),ver(v){} }; struct Matching { int ww; int uu; Matching(int w=0,int u=0):ww(w),uu(u){} void print(){ cout<<"("<<ww<<","<<uu<<") "; } }; int N1,N2; //點數,N1為V,N2為U vector<vertex>V; vector<Matching>M; public: B_Graph(int n1,int n2):N1(n1),N2(n2) { vertex tmp; Matching tmp1; for(int i=0;i<=N1+N2;i++) V.push_back(tmp); for(int i=0;i<=N1;i++) M.push_back(tmp1); } void merge(int i,int j) { V[i].adj.push_back(j); } void Max_B_Maching() { queue<int>Q; int i1=0; while(i1++<N1) Q.push(i1); while(!Q.empty()) { int w=Q.front();Q.pop(); if(w<=N1) //即w屬於V { for(unsigned int i=0;i<V[w].adj.size();i++) { int u=V[w].adj[i]; if(V[u].flag==0) { Matching tmp(w,u); M[w]=tmp; V[u].flag=1; V[w].flag=1; int v=w; while(V[v].ver) { u=V[v].ver; v=V[u].ver; Matching tmp2(v,u); M[v]=tmp2; V[v].flag=1; } for(int i=1;i<=N1+N2;i++) V[i].ver=0; while(!Q.empty()) Q.pop(); for(int i=1;i<=N1;i++) if(V[i].flag==0) Q.push(i); break; } else { if((M[w].ww!=w||M[w].uu!=u)&&V[u].ver==0) { V[u].ver=w; Q.push(u); } } } } else { int i=1; for(;i<=N1;i++) if(M[i].uu==w) { V[i].ver=w; break; } Q.push(i); } } } void print_M_maching() { for(int i=1;i<=N1;i++) if(M[i].ww!=0) M[i].print(); } int max_maching() { int Max=0; for(int i=1;i<=N1;i++) if(M[i].ww!=0) Max++; return Max; } }; int main() { freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); int v,u,edge; while(cin>>v>>u>>edge) { B_Graph G(u,v); int a,b; while(edge--) { cin>>a>>b; G.merge(a,b); } G.Max_B_Maching(); G.print_M_maching(); cout<<endl<<"The Max_maching number is:"<<G.max_maching()<<endl; } fclose(stdin); fclose(stdout); return 0; }
下面是in.txt的測試資料:
5 5 10
1 6
1 7
2 6
3 6
3 8
4 8
4 9
4 10
5 9
5 10
4 4 8
1 6
2 6
2 7
3 6
3 7
4 5
4 7
4 8
最後是out.txt的結果:
(1,7) (2,6) (3,8) (4,9) (5,10)
The Max_maching number is:5
(1,6) (2,7) (4,5)
The Max_maching number is:3
結果正確!OK!