HDU 3657 Game 网络流--最大独立集

来源:互联网 发布:成都医疗大数据公司 编辑:程序博客网 时间:2024/05/17 22:31

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?
 
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 - 最小割。
 
View Code
  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             else108                 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                 else118                     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 }