Game
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 668 Accepted Submission(s): 262
Problem Description
onmylove has invented a game on n × m grids. There is one positive integer on each grid. Now you can take the numbers from the grids to make your final score as high as possible. The way to get score is like the following: ● At the beginning, the score is 0; ● If you take a number which equals to x, the score increase x; ● If there appears two neighboring empty grids after you taken the number, then the score should be decreased by 2(x&y). Here x and y are the values used to existed on these two grids. Please pay attention that "neighboring grids" means there exits and only exits one common border between these two grids.
Since onmylove thinks this problem is too easy, he adds one more rule: ● Before you start the game, you are given some positions and the numbers on these positions must be taken away. Can you help onmylove to calculate: what's the highest score onmylove can get in the game?
Since onmylove thinks this problem is too easy, he adds one more rule: ● Before you start the game, you are given some positions and the numbers on these positions must be taken away. Can you help onmylove to calculate: what's the highest score onmylove can get in the game?
Input
Multiple input cases. For each case, there are three integers n, m, k in a line. n and m describing the size of the grids is n ×m. k means there are k positions of which you must take their numbers. Then following n lines, each contains m numbers, representing the numbers on the n×m grids.Then k lines follow. Each line contains two integers, representing the row and column of one position and you must take the number on this position. Also, the rows and columns are counted start from 1. Limits: 1 ≤ n, m ≤ 50, 0 ≤ k ≤ n × m, the integer in every gird is not more than 1000.
Output
For each test case, output the highest score on one line.
Sample Input
2 2 1
2 2
2 2
1 1
2 2 1
2 7
4 1
1 1
Sample Output
4
9
思路:最大独立集 = ∑V - 最小覆盖集,相对HDU 1565 而言,此题多了一个条件,那就是有些点是必取的,而且相邻点也是可取的,只不过要减去分数2*(x&y),其中y在x之后取,且x和y相邻。构图的时候,构造源点和横纵坐标之和为偶数的点相连,流量为该点的值,如果该点是必选,则添加多这样的一条边,流量则为INF;构造汇点,将横纵坐标之和为奇数的点和汇点相连,流量为该点的值,同样的,若该点必选,则添加流量为INF的边。最后,将所有偶数点和他们的邻接点相连,流量为2*(x&y),其中x是偶数的点,y是他相邻的点。然后直接求出最小割,答案为∑V - 最小割。
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define INF 0x7fffffff 6 #define MAX 60000 7 8 using namespace std; 9 10 struct node 11 { 12 int to,val,next; 13 }; 14 15 node edge[MAX*15]; 16 int head[MAX]; 17 int idx; 18 19 int N,M,K; 20 int source,sink,pt; 21 int map[100][100]; 22 23 int gap[MAX],dis[MAX]; 24 25 void addNode(int from,int to,int val) 26 { 27 edge[idx].to = to; 28 edge[idx].val = val; 29 edge[idx].next = head[from]; 30 head[from] = idx ++; 31 edge[idx].to = from; 32 edge[idx].val = 0; 33 edge[idx].next = head[to]; 34 head[to] = idx ++; 35 } 36 37 int dfs(int cur,int cur_val) 38 { 39 if(cur == sink) 40 return cur_val; 41 int min_dis = pt - 1, temp_val = cur_val; 42 for(int i=head[cur]; i!=-1; i=edge[i].next) 43 { 44 int to = edge[i].to, value = edge[i].val; 45 if(value > 0) 46 { 47 if(dis[to] + 1 == dis[cur]) 48 { 49 int val = min(temp_val,edge[i].val); 50 val = dfs(to,val); 51 temp_val -= val; 52 edge[i].val -= val; 53 edge[i^1].val += val; 54 if(dis[source] >= pt) 55 return cur_val - temp_val; 56 if(temp_val == 0) 57 break; 58 } 59 if(min_dis > dis[to]) 60 min_dis = dis[to]; 61 } 62 } 63 if(cur_val == temp_val) 64 { 65 --gap[dis[cur]]; 66 if(!gap[dis[cur]]) 67 dis[source] = pt; 68 dis[cur] = min_dis + 1; 69 ++gap[dis[cur]]; 70 } 71 return cur_val - temp_val; 72 } 73 74 int sap() 75 { 76 memset(gap,0,sizeof(gap)); 77 memset(dis,0,sizeof(dis)); 78 gap[source] = pt; 79 int ret = 0; 80 while(dis[source] < pt) 81 ret += dfs(source,INF); 82 return ret; 83 } 84 85 int main() 86 { 87 while(~scanf("%d%d%d",&N,&M,&K)) 88 { 89 int sum = 0; 90 for(int i=1; i<=N; i++) 91 for(int j=1; j<=M; j++) 92 { 93 scanf("%d",&map[i][j]); 94 sum += map[i][j]; 95 } 96 idx = 0; 97 memset(head,-1,sizeof(head)); 98 source = 0; 99 sink = N*M + 1; 100 pt = sink + 1; 101 for(int i=1; i<=K; i++) 102 { 103 int x,y; 104 scanf("%d%d",&x,&y); 105 if((x+y)%2==0) 106 addNode(source,y+(x-1)*M,INF); 107 else 108 addNode(y+(x-1)*M,sink,INF); 109 } 110 for(int i=1; i<=N; i++) 111 { 112 for(int j=1; j<=M; j++) 113 { 114 int temp = j+(i-1)*M; 115 if((i+j)%2 == 0) 116 addNode(source,temp,map[i][j]); 117 else 118 addNode(temp,sink,map[i][j]); 119 } 120 } 121 for(int i=1; i<=N; i++) 122 { 123 for(int j=1; j<=M; j++) 124 { 125 if((i+j)%2==0) 126 { 127 int temp = j+(i-1)*M; 128 if(j-1>0) 129 addNode(temp,temp-1,2*(map[i][j]&map[i][j-1])); 130 if(j+1<=M) 131 addNode(temp,temp+1,2*(map[i][j]&map[i][j+1])); 132 if(i-1>0) 133 addNode(temp,temp-M,2*(map[i][j]&map[i-1][j])); 134 if(i+1<=N) 135 addNode(temp,temp+M,2*(map[i][j]&map[i+1][j])); 136 } 137 } 138 } 139 int ans = sap(); 140 printf("%d\n",sum-ans); 141 } 142 return 0; 143 }