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

 

你可能感兴趣的:(bat)