標籤:os io for 問題 演算法 amp size c
/*這道題將每行x看成是結點x,沒列y看成是結點y,而障礙物的座標xy看成是從x到y的一條邊。建圖後問題就變成了,找最少的點,使得這些點與所有的邊相鄰,即最小點覆蓋,用匈牙利演算法解決。-------------------------------定理:最小點覆蓋數 = 最大匹配數,即求圖的最大匹配即可,匈牙利演算法-------------------------------模板講解:bool find(int v){ for(int i=1; i<=n; i++) { if(g[v][i] && !vis[i])如果結點i和v相鄰並且未被尋找過 { vis[i] = true;標記結點i為已尋找過 if(link[i] == 0 || find(link[i]))link[i] == 0表示i不再前一個匹配M中||i在匹配M中,但是從與i相鄰的節點出發可以有增廣路 { link[i] = v;記錄尋找成功記錄 return true;返回尋找成功 } } } return false;}-------------------------------匈牙利演算法介紹:匈牙利演算法是由匈牙利數學家Edmonds於1965年提出,因而得名。匈牙利演算法是基於Hall定理中充分性證明的思想,它是部圖匹配最常見的演算法,該演算法的核心就是尋找增廣路徑,它是一種用增廣路徑求二分圖最大匹配的演算法。---------------------------------*/#include <iostream>#include <cstdio>#include <cstring>#define INF 0x3f3f3f3fusing namespace std;int n,k,r,c;int g[550][550];bool vis[10010];int link[10010];bool find(int v){ for(int i=1; i<=n; i++) { if(g[v][i] && !vis[i]) { vis[i] = true; if(link[i] == 0 || find(link[i])) { link[i] = v; return true; } } } return false;}int main(){ //freopen("input.txt","r",stdin); int ans; while(scanf("%d%d",&n,&k) != EOF) { memset(g,0,sizeof(g)); memset(link,0,sizeof(link)); for(int i = 0; i < k; i++) { scanf("%d%d",&r,&c); g[r][c] = 1; } ans = 0; for(int i=1; i<=n; i++) { memset(vis,0,sizeof(vis));//清空上次搜尋時的標記 if(find(i))//從節點i嘗試擴充 ans++; } printf("%d\n",ans); } return 0;}
---------------------------------------------------------------------
戰鬥,毫不退縮;奮鬥,永不停歇~~~~~~~~~~