1. 程式人生 > >HDU 1281 - 棋盤遊戲 - [二分圖最大匹配]

HDU 1281 - 棋盤遊戲 - [二分圖最大匹配]

鏈接 ems 枚舉 一個 輸入 string ima () have

題目鏈接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1281

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

Problem Description 小希和Gardon在玩一個遊戲:對一個N*M的棋盤,在格子裏放盡量多的一些國際象棋裏面的“車”,並且使得他們不能互相攻擊,這當然很簡單,但是Gardon限制了只有某些格子才可以放,小希還是很輕松的解決了這個問題(見下圖)註意不能放車的地方不影響車的互相攻擊。
所以現在Gardon想讓小希來解決一個更難的問題,在保證盡量多的“車”的前提下,棋盤裏有些格子是可以避開的,也就是說,不在這些格子上放車,也可以保證盡量多的“車”被放下。但是某些格子若不放子,就無法保證放盡量多的“車”,這樣的格子被稱做重要點。Gardon想讓小希算出有多少個這樣的重要點,你能解決這個問題麽?
技術分享
Input 輸入包含多組數據,
第一行有三個數N、M、K(1<N,M<=100 1<K<=N*M),表示了棋盤的高、寬,以及可以放“車”的格子數目。接下來的K行描述了所有格子的信息:每行兩個數X和Y,表示了這個格子在棋盤中的位置。 Output 對輸入的每組數據,按照如下格式輸出:
Board T have C important blanks for L chessmen. Sample Input 3 3 4 1 2 1 3 2 1 2 2 3 3 4 1 2 1 3 2 1 3 2 Sample Output Board 1 have 0 important blanks for 2 chessmen. Board 2 have 3 important blanks for 3 chessmen. 題解: 參考http://www.cnblogs.com/dilthey/p/7647870.html博文中的方法②; 因為這次沒有墻能隔開車與車之間的攻擊,故直接將整行整列縮成點,然後求出max match; 但是如何尋找其中的“必須邊”呢? 比較好想的方法就是直接暴力枚舉最大匹配中的匹配邊,如果把它去掉還能不能得到一樣的最大匹配數: 如果不能,就是必須邊,cnt+=1; AC代碼:
 1
#include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #define MAX 203 5 using namespace std; 6 int n,m,k; 7 int edge[MAX][MAX]; 8 int matching[MAX]; 9 int vis[MAX]; 10 void init(){memset(edge,0,sizeof(edge));} 11 void add_edge(int u,int v){edge[u][v]=edge[v][u]=1;} 12 bool
dfs(int u) 13 { 14 for(int v=1;v<=n+m;v++) 15 { 16 if(!edge[u][v]) continue; 17 if (!vis[v]) 18 { 19 vis[v]=1; 20 if(!matching[v] || dfs(matching[v])) 21 { 22 matching[v]=u; 23 matching[u]=v; 24 return true; 25 } 26 } 27 } 28 return false; 29 } 30 int hungarian() 31 { 32 int ret=0; 33 memset(matching,0,sizeof(matching)); 34 for(int i=1;i<=n;i++) 35 { 36 if(!matching[i]) 37 { 38 memset(vis,0,sizeof(vis)); 39 if(dfs(i)) ret++; 40 } 41 } 42 return ret; 43 } 44 int mp[103][103],match[MAX][MAX]; 45 int main() 46 { 47 int kase=0; 48 while(scanf("%d%d%d",&n,&m,&k)!=EOF) 49 { 50 memset(mp,0,sizeof(mp)); 51 for(int i=1,r,c;i<=k;i++) 52 { 53 scanf("%d%d",&r,&c); 54 mp[r][c]=1; 55 } 56 57 init(); 58 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(mp[i][j]) add_edge(i,j+n); 59 int max_match=hungarian(); 60 61 int cnt=0; 62 memset(match,0,sizeof(match)); 63 for(int i=1;i<=n+m;i++) for(int j=n+1;j<=n+m;j++) if(matching[i]==j && matching[j]==i) match[i][j]=1; 64 for(int i=1;i<=n+m;i++) 65 { 66 for(int j=n+1;j<=n+m;j++) 67 { 68 if(match[i][j]) 69 { 70 edge[i][j]=0; 71 if(hungarian()<max_match) cnt++; 72 edge[i][j]=1; 73 } 74 } 75 } 76 77 printf("Board %d have %d important blanks for %d chessmen.\n",++kase,cnt,max_match); 78 } 79 }

HDU 1281 - 棋盤遊戲 - [二分圖最大匹配]