1. 程式人生 > >Land of Farms HDU - 5556 二分圖匹配

Land of Farms HDU - 5556 二分圖匹配

Farmer John and his brothers have found a new land. They are so excited and decide to build new farms on the land. The land is a rectangle and consists of  N×MN×Mgrids. A farm consists of one or more connected grids. Two grids are adjacent if they share a common border, i.e. their Manhattan distance is exactly 1. In a farm, two grids are considered connected if there exist a series of adjacent grids, which also belong to that farm, between them. 

Farmer John wants to build as many farms as possible on the new land. It is required that any two farms should not be adjacent. Otherwise, sheep from different farms would fight on the border. This should be an easy task until several ancient farms are discovered. 

Each of the ancient farms also consists of one or more connected grids. Due to the respect to the ancient farmers, Farmer John do not want to divide any ancient farm. If a grid from an ancient farm is selected in a new farm, other grids from the ancient farm should also be selected in the new farm. Note that the ancient farms may be adjacent, because ancient sheep do not fight each other. 

The problem is a little complicated now. Can you help Farmer John to find a plan with the maximum number of farms? 

InputThe first line of input contains a number TT indicating the number of test cases (T200T≤200). 

Each test case starts with a line containing two integers NN and MM, indicating the size of the land. Each of the following NN lines contains 

M">MM characters, describing the map of the land (1N,M101≤N,M≤10). A grid of an ancient farm is indicated by a single digit (0-9). Grids with the same digit belong to the same ancient farm. Other grids are denoted with a single character “ .”. It is guaranteed that all test cases are valid. 
OutputFor each test case, output a single line consisting of “ Case #X: Y”. XX is the test case number starting from 1. YY is the maximum number of new farms.Sample Input

3
3 4
..3.
023.
.211
2 3
...
...
4 4
1111
1..1
1991
1111

Sample Output

Case #1: 4
Case #2: 3
Case #3: 1
題意:
一個N*M的矩陣,其中“.”代表空地,“0-9”代表古代建築,我們如果選擇了一個編號的古代建築想要建立,
那麼對應就要將全部該編號的建築建立起來,如果在空地上建築,只建立當前點。問最多能夠建立多少種建築,
並且每兩種建築之間沒有公共邊。
這題我做的非常吃力。

冷靜分析 先考慮沒有任何建築的情況,也就是兩兩不能相連,看有多少個建築
這個就是跑一邊二分圖最大匹配就出來了。
知道這個之後,然後再思考建築總共只有10種,所以列舉一下有哪幾種建築存在,
暴搜每一種合法的情況。
細節一定要處理好,選定的建築周圍的空白格子根據題意要摳出來。選的的建築不能有相連;
ans=扣點後的空白的數目-扣點後的空白的數目的最大匹配+選擇的建築的數目

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <set>
  7 #include <iostream>
  8 #include <map>
  9 #include <stack>
 10 #include <string>
 11 #include <vector>
 12 #define  pi acos(-1.0)
 13 #define  eps 1e-6
 14 #define  fi first
 15 #define  se second
 16 #define  rtl   rt<<1
 17 #define  rtr   rt<<1|1
 18 #define  bug         printf("******\n")
 19 #define  mem(a,b)    memset(a,b,sizeof(a))
 20 #define  name2str(x) #x
 21 #define  fuck(x)     cout<<#x" = "<<x<<endl
 22 #define  f(a)        a*a
 23 #define  sf(n)       scanf("%d", &n)
 24 #define  sff(a,b)    scanf("%d %d", &a, &b)
 25 #define  sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
 26 #define  sffff(a,b,c,d) scanf("%d %d %d %d", &a, &b, &c, &d)
 27 #define  pf          printf
 28 #define  FRE(i,a,b)  for(i = a; i <= b; i++)
 29 #define  FREE(i,a,b) for(i = a; i >= b; i--)
 30 #define  FRL(i,a,b)  for(i = a; i < b; i++)+
 31 #define  FRLL(i,a,b) for(i = a; i > b; i--)
 32 #define  FIN         freopen("data.txt","r",stdin)
 33 #define  gcd(a,b)    __gcd(a,b)
 34 #define  lowbit(x)   x&-x
 35 using namespace std;
 36 typedef long long  LL;
 37 typedef unsigned long long ULL;
 38 const int mod = 1e9 + 7;
 39 const int maxn = 3e6 + 10;
 40 const int INF = 0x3f3f3f3f;
 41 const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
 42 char a[15][15];
 43 int dx[4] = {0, 0, 1, -1};
 44 int dy[5] = {1, -1, 0, 0};
 45 int t, cas = 1, n, m, sum, ans, use[15], vis[15];
 46 int vis2[15][15], vis3[15][15], match[3000], vis4[3000];
 47 vector<int>mp[105];
 48 int Find ( int u ) {
 49     for ( int i = 0 ; i < mp[u].size(); i++ ) {
 50         int v = mp[u][i];
 51         if ( !vis4[v] ) {
 52             vis4[v] = 1;
 53             if ( match[v] == -1 || Find ( match[v] ) ) {
 54                 match[v] = u;
 55                 return 1;
 56             }
 57         }
 58     }
 59     return 0;
 60 }
 61 void solve() {
 62     mem ( vis2, 0 );
 63     for ( int i = 0 ; i < n ; i++ ) {
 64         for ( int j = 0 ; j < m ; j++ ) {
 65             if ( a[i][j] == '.' ) {
 66                 for ( int k = 0; k < 4 ; k++ ) {
 67                     int x = i + dx[k], y = j + dy[k];
 68                     if ( x >= 0 && x < n && y >= 0 && y < m && a[x][y] != '.' && vis[a[x][y] - '0'] )  vis2[i][j] = 1;
 69                 }
 70             } else {
 71                 vis2[i][j] = 1;
 72                 for ( int k = 0; k < 4 ; k++ ) {
 73                     int x = i + dx[k], y = j + dy[k];
 74                     if ( x >= 0 && x < n && y >= 0 && y < m ) {
 75                         if ( vis[a[i][j] - '0'] == 1 && vis[a[x][y] - '0'] == 1 && a[i][j] != a[x][y] ) {
 76                             return ;
 77                         }
 78                     }
 79                 }
 80             }
 81         }
 82     }
 83     int num = 0;
 84     for ( int i = 0 ; i < n ; i++ )
 85         for ( int j = 0 ; j < m ; j++ )
 86             if ( !vis2[i][j] ) vis3[i][j] = ++num;
 87     for ( int i = 0 ; i <= n * m ; i++ ) mp[i].clear();
 88     for ( int i = 0 ; i < n ; i++ ) {
 89         for ( int j = 0 ; j < m ; j++ ) {
 90             if ( !vis2[i][j] ) {
 91                 for ( int k = 0 ; k < 4 ; k++ ) {
 92                     int x = i + dx[k], y = j + dy[k];
 93                     if ( x >= 0 && x < n && y >= 0 && y < m && !vis2[x][y] ) mp[vis3[i][j]].push_back ( vis3[x][y] );
 94                 }
 95             }
 96         }
 97     }
 98     int res = 0;
 99     mem ( match, -1 );
100     for ( int i = 1 ; i <= num ; i++ ) {
101         mem ( vis4, 0 );
102         if ( Find ( i ) ) res++;
103     }
104     int key = 0;
105     for ( int i = 0 ; i < sum ; i++ ) if ( vis[i] ) key++;
106   //  bug, fuck ( key ), fuck ( num ), fuck ( res );
107     ans = max ( ans, key + num - res / 2 );
108 }
109 void dfs ( int now ) {
110     if ( now == sum ) {
111         solve();
112         return ;
113     }
114     vis[now] = 1;
115     dfs ( now + 1 );
116     vis[now] = 0;
117     dfs ( now + 1 );
118 }
119 int main() {
120    // FIN;
121     sf ( t );
122     while ( t-- ) {
123         sum = 0;
124         mem ( use, -1 );
125         sff ( n, m );
126         for ( int i = 0 ; i < n ; i++ ) {
127             scanf ( "%s", a[i] );
128             for ( int j = 0 ; j < m ; j++ ) {
129                 if ( a[i][j] != '.' ) {
130                     if ( use[a[i][j] - '0'] != -1 ) a[i][j] = use[a[i][j] - '0'] + '0';
131                     else use[a[i][j] - '0'] = sum++, a[i][j] = use[a[i][j] - '0'] + '0';
132                 }
133             }
134         }
135         ans = 0;
136         dfs ( 0 );
137         printf ( "Case #%d: %d\n", cas++, ans );
138     }
139     return 0;
140 }
View Code