匈牙利演算法(最小點覆蓋)poj3041
阿新 • • 發佈:2018-12-10
題目意思是一次可以毀掉一行或者一列,要求至少毀多少次才能將圖上的x都消滅掉。
簡單的解釋一下最小點覆蓋:在圖中用最少的點,覆蓋圖中所有的邊
將每一行或者列想象成點,每個x想象成一條邊,於是此題很自然的轉換成為了最小點覆蓋問題。
而二分圖的最小點覆蓋數 = 二分圖的最大匹配。
於是就用匈牙利演算法求這個圖的最大匹配就好啦。
用人和座位分別表示二分圖的x集和y集,於是匈牙利演算法大概每一趟過程可以描述成以下形式
#include<stdio.h> #include<iostream> #include<cstring> #include<vector> using namespace std; int used[10004];//註釋1 vector<int> map[504];//用二維向量模擬鄰接表 int per[10004];// per[x]的意思是x號座位上坐的是誰 int n, m; bool find(int x); int main() { int ans = 0; scanf("%d%d",&n,&m); int h,l; for(int i=0; i<m; i++) { scanf("%d%d",&h,&l); map[h].push_back(l); } for(int i=1; i<=n; i++) { memset(used,0,sizeof(used)); if(find(i) ) ans++; } printf("%d",ans); return 0; } bool find(int x){ for(int i=0; i<map[x].size(); i++)//遍歷x號老哥能坐的所有座位 { if( !used[map[x][i]] ) //註釋1 { used[map[x][i]] = 1; if( per[map[x][i]] == 0 || find(per[map[x][i]])) { per[map[x][i]] = x; return true; } } } return false; }
註釋1的解釋:
四號大哥只能坐3號位置,為了防止一個一個騰座位的時候,有人將3號座位又坐了,因此加以標記。表示幾號座位是準備給騰出來的,不能在騰的過程中讓別人坐了