HDU 1569 方格取数(2)

方格取数(2)

Time Limit: 5000ms
Memory Limit: 32768KB
This problem will be judged on HDU. Original ID: 1569
64-bit integer IO format: %I64d      Java class name: Main
 
给你一个m*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大。
 

Input

包括多个测试实例,每个测试实例包括2整数m,n和m*n个非负数(m<=50,n<=50)
 

Output

对于每个测试实例,输出可能取得的最大的和
 

Sample Input

3 3
75 15 21 
75 15 28 
34 70 5

Sample Output

188

Source

 
解题:最大点权独立集 = sum - 最小点权独立集
 
  最小点权独立集 = 最小割 = 最大流。
  黑白棋盘。i+j为偶数的点,直接与超级汇点连接,权值为改点的权值。i+j为奇数的点,与超级源点连接,权值为该点权值。并且,同时与它的相邻四个方向的点连接,权值为无限大。
 
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <climits>
 7 #include <vector>
 8 #include <queue>
 9 #include <cstdlib>
10 #include <string>
11 #include <set>
12 #include <stack>
13 #define LL long long
14 #define pii pair<int,int>
15 #define INF 0x3f3f3f3f
16 using namespace std;
17 const int maxn = 3000;
18 struct arc {
19     int to,flow,next;
20     arc(int x = 0,int y = 0,int z = 0) {
21         to = x;
22         flow = y;
23         next = z;
24     }
25 };
26 arc e[maxn*10];
27 int head[maxn],d[maxn],tot;
28 int S,T,q[maxn],hd,tail,n,m;
29 void add(int u,int v,int flow) {
30     e[tot] = arc(v,flow,head[u]);
31     head[u] = tot++;
32     e[tot] = arc(u,0,head[v]);
33     head[v] = tot++;
34 }
35 bool bfs() {
36     for(int i = 1; i <= T; i++) d[i] = 0;
37     d[S] = 1;
38     hd = tail = 0;
39     q[tail++] = S;
40     while(hd < tail) {
41         int u = q[hd++];
42         for(int i = head[u]; ~i; i = e[i].next) {
43             if(e[i].flow && !d[e[i].to]) {
44                 d[e[i].to] = d[u]+1;
45                 q[tail++] = e[i].to;
46             }
47         }
48     }
49     return d[T];
50 }
51 int dfs(int u,int low) {
52     int tmp = 0,f;
53     if(u == T || !low) return low;
54     for(int i = head[u]; ~i; i = e[i].next) {
55         if(d[e[i].to] == d[u]+1 && (f = dfs(e[i].to,min(low,e[i].flow)))) {
56             tmp += f;
57             e[i].flow -= f;
58             e[i^1].flow += f;
59             low -= f;
60             if(!low) break;
61         }
62     }
63     return tmp;
64 }
65 int main() {
66     while(~scanf("%d %d",&n,&m)) {
67         memset(head,-1,sizeof(head));
68         int sum = tot = 0,o,ans = 0;
69         S = n*m+1;
70         T = n*m+2;
71         for(int i = 1; i <= n; i++)
72             for(int j = 1; j <= m; j++) {
73                 scanf("%d",&o);
74                 sum += o;
75                 int tmp = (i-1)*m + j;
76                 if((i+j)&1) {
77                     add(S,tmp,o);
78                     if(i > 1) add(tmp,tmp-m,INF);
79                     if(j > 1) add(tmp,tmp-1,INF);
80                     if(i < n) add(tmp,tmp+m,INF);
81                     if(j < m) add(tmp,tmp+1,INF);
82                 } else add(tmp,T,o);
83             }
84         while(bfs()) ans += dfs(S,INF);
85         printf("%d
",sum-ans);
86     }
87     return 0;
88 }
View Code
原文地址:https://www.cnblogs.com/crackpotisback/p/3973898.html