二分圖的基本概念:
二分圖又稱作二部圖,是圖論中的一種特殊模型。 設G=(V,E)是一個無向圖,如果頂點V可分割為兩個互不相交的子集(A,B),並且圖中的每條邊(i,j)所關聯的兩個頂點i和j分別屬於這兩個不同的頂點集(i in A,j in B),則稱圖G為一個二分圖。
比如:
我們一般把圖的兩部分稱為X部和Y部,一個圖的所有點如果能被兩個獨立的點集,那就認為這個圖是二分圖
二分圖的判斷一般通過染色的方法來進行判段,可以寫成dfs或則bfs的寫法
bool dfs(int v,int c) { color[v]=c; for(int i=0;i<n;i++) { if(edge[v][i]==1) { if(color[i]==c) return false; if(color[i]==0&&!dfs(i,-c)) return false; } } return true; } void solve() { int flag=0; for(int i=0;i<n;i++) { if(color[i]==0) { if(!dfs(i,1)) { cout<<"no"<<endl; flag=1; break; } } } if(!flag) cout<<"yes"<<endl; }
bfs寫法
bool bfs(int s) { color[s] = 1; queue<int> que; que.push(s); while(!que.empty()) { int from = que.front(); que.pop(); for(int i = 1; i <= V; i++) { // 如果相鄰的點沒有上色就給這個點上色 if(G[from][i] && color[i] == 0) { que.push(i); color[i] = -color[from]; } // 如果相鄰的顏色相同則返回false if(G[from][i] && color[i] == color[from]) return false; } } // 如果所有的點都被染過色,且相鄰的點顏色都不一樣,返回true return true; }
接下來就是介紹匹配:
一個匹配是一個邊的集合,任何匹配的邊之間沒有公共頂點。
最大匹配:一個圖的所有匹配中,邊數最多的匹配稱為最大匹配。如果所有定點都是匹配頂點,則稱這個匹配為完美匹配。
我們一般通過匈牙利算法來求一個二分圖的最大匹配,其算法的核心是求增廣路徑。
交替路:從一個未匹配點出發,依次經過非匹配邊、匹配邊、非匹配邊...形成的路徑叫交替路。*
增廣路:從一個未匹配點出發,走交替路,如果途徑另一個未匹配點(出發的點不算),則這條交替路稱為增廣路(agumenting path)。
我們每次找到一個增廣路,所得到的匹配的邊數都會增加一條,因此我們可以通過求所有點的增廣路徑來求最大匹配的邊數
匈牙利算法的模板如下:
bool dfs(int x) { for(int i=1;i<=p;i++) { if(!used[i]&&map[x][i]==1) { used[i]=1; if(!link[i]||dfs(link[i])) { link[i]=x; return true; } } } return false; } void xyl() { for(int i=1;i<=n;i++) { memset(used,0,sizeof(used)); if(dfs(i)) counts++; } }
PS.練習題:hdu 1045,hdu 2444,hdu 1083
此外還有二分圖的最小頂點覆蓋,最大獨立集,最大團等知識,求的方法和匈牙利算法的差不多可以參考如下博客
https://www.cnblogs.com/jianglangcaijin/p/6035945.html
剩下的帶權二分圖過幾天在補充