hdu 5093 Battle ships 匈牙利 很巧妙的建图思路

//这题逼我把匈牙利学了 之前一直很勤快敲网络流 而且不以为耻反以为荣

解:首先按行扫描编号,如果在同一块中(即可以相互攻击),那么将其标为相同的数组,对列也做同样的操作。

然后扫描整张图,如果行编号为a的块与列编号为b的块有公共点,那么将二部图中A集合中a点与B集合中b点相连。最后求出来最大二分匹配数就是答案。

(为什么这样做)首先很明显的,二部图中每一条边就对应原图中的一个点,因此,匹配数=边数=最多可放置的战舰数,另外二分图每个点只能匹配一次,对应到原题中就是每一块只能放置一个战舰.

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<queue>
  8 #include<vector>
  9 #include<map>
 10 #include<stack>
 11 #include<string>
 12 
 13 using namespace std;
 14 
 15 const int INF=2000000000;
 16 
 17 int T;
 18 int n,m,num_a,num_b;
 19 char c[51][51];
 20 int a[51][51];
 21 int b[51][51];
 22 bool adj[2501];
 23 int link[2501];
 24 int f[2501][2501];
 25 bool used[2501];
 26 
 27 bool work(int x){
 28     for (int i=1;i<=num_b;i++){
 29             if (f[x][i] && !adj[i]){
 30                     adj[i]=1;
 31                     if (!used[i] || work(link[i])){
 32                             link[i]=x;
 33                             used[i]=1;
 34                             return true;
 35                     }
 36             }
 37     }
 38     return false;
 39 }
 40 
 41 int main(){
 42     scanf("%d",&T);
 43     for (int cas=1;cas<=T;cas++){
 44             scanf("%d%d",&n,&m);
 45             for (int i=0;i<n;i++) scanf("%s",c[i]);
 46             memset(a,0,sizeof(a));
 47             memset(b,0,sizeof(b));
 48             int t=1;
 49             bool flag=0;
 50             for (int i=0;i<n;i++){
 51                     if (flag){
 52                             t++;
 53                             flag=false;
 54                     }
 55                     for (int j=0;j<m;j++){
 56                             if (c[i][j]=='*') {
 57                                     a[i][j]=t;
 58                                     flag=true;
 59                             }
 60                             if (flag && c[i][j]=='#'){
 61                                     flag=false;
 62                                     t++;
 63                             }
 64                     }
 65             }
 66             if (flag) t++;
 67             num_a=t-1;
 68             t=1;
 69             flag=0;
 70             for (int j=0;j<m;j++){
 71                     if (flag){
 72                             t++;
 73                             flag=false;
 74                     }
 75                     for (int i=0;i<n;i++){
 76                             if (c[i][j]=='*') {
 77                                     b[i][j]=t;
 78                                     flag=true;
 79                             }
 80                             if (flag && c[i][j]=='#'){
 81                                     flag=false;
 82                                     t++;
 83                             }
 84                     }
 85             }
 86             if (flag) t++;
 87             num_b=t-1;
 88             memset(used,0,sizeof(used));
 89             memset(f,0,sizeof(f));
 90             memset(link,0,sizeof(link));
 91             for (int i=0;i<n;i++){
 92                     for (int j=0;j<m;j++){
 93                             if (a[i][j]!=0 && b[i][j]!=0){
 94                                     f[a[i][j]][b[i][j]]=1;
 95                             }
 96                     }
 97             }
 98             int ans=0;
 99             for (int i=1;i<=num_a;i++){
100                     memset(adj,0,sizeof(adj));
101                     if (work(i)) ans++;
102             }
103             printf("%d\n",ans);
104     }
105     return 0;
106 }
107 /*
108 2
109 4 4
110 *ooo
111 o###
112 **#*
113 ooo*
114 4 4
115 #***
116 *#**
117 **#*
118 ooo#
119 */
View Code

 

posted @ 2015-07-17 16:14  鼠宝宝  阅读(306)  评论(0编辑  收藏  举报