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 */