网络流二十四题之九 —— 方格取数问题(GRID)

来源:互联网 发布:免费手机屏幕录制软件 编辑:程序博客网 时间:2024/06/15 08:53

方格取数问题


Description

在一个有 mn 个方格的棋盘中,每个方格中有一个正整数。
现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大。
试设计一个满足要求的取数算法。


Input

文件第 1 行有 2 个正整数 mn,分别表示棋盘的行数和列数。
接下来的 m 行,每行有 n 个正整数,表示棋盘方格中的数。


Output

程序运行结束时,将取数的最大总和输出到文件中。


Sample Input

3 3
1 2 3
3 2 3
2 3 1


Sample Output

11


HINT

mn 均为小于 30 的正整数,方格中的数都为正整数。


Solution

第一次做棋盘形的网络流,有点小激动。
一看就觉得这个题目有点水。

把横坐标和纵坐标相加为偶数的格子往四周连容量为无限大的边。
将源点与(横坐标和纵坐标相加为偶数的格子)连一条容量为其格子上的数字的边。
将汇点与(横坐标和纵坐标相加为奇数的格子)连一条容量为七个字上的数字的边。

求最小切割,然后用所有的数字之和减去最小切割即可。


Code

[cpp]
  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <cstring>  
  4. #include <queue>  
  5.   
  6. #define Min(x,y) ((x)<(y)?(x):(y))  
  7. #define PLA(x,y) ((((x)-1)*n)+(y))  
  8. #define INF 0x3f3f3f3f  
  9. #define ss 9999  
  10. #define tt 10000  
  11.   
  12. using namespace std;  
  13.   
  14. int m,n,cnt,sum;  
  15. int map[30][30];  
  16. int head[101000],nxt[1000010];  
  17. int data[1000010],flow[1000010];  
  18. int dis[101000];  
  19. queue<int>q;  
  20.   
  21. void add(int x,int y,int z){  
  22.     nxt[cnt]=head[x];data[cnt]=y;flow[cnt]=z;head[x]=cnt++;  
  23.     nxt[cnt]=head[y];data[cnt]=x;flow[cnt]=0;head[y]=cnt++;   
  24. }  
  25.   
  26. bool BFS(){  
  27.     memset(dis,-1,sizeof dis);  
  28.     dis[ss]=0;  
  29.     q.push(ss);  
  30.     while(!q.empty()){  
  31.         int now=q.front();  
  32.         q.pop();  
  33.         for(int i=head[now];i!=-1;i=nxt[i]){  
  34.             if(flow[i]&&dis[data[i]]==-1){  
  35.                 q.push(data[i]);  
  36.                 dis[data[i]]=dis[now]+1;   
  37.             }  
  38.         }  
  39.     }  
  40.     return dis[tt]>0;  
  41. }  
  42.   
  43. int dfs(int now,int low){  
  44.     if(now==tt)return low;  
  45.     int Low;  
  46.     for(int i=head[now];i!=-1;i=nxt[i]){  
  47.         if(flow[i]&&dis[data[i]]==dis[now]+1){  
  48.             if(Low=dfs(data[i],Min(low,flow[i]))){  
  49.                 flow[i]-=Low;  
  50.                 flow[i^1]+=Low;  
  51.                 return Low;  
  52.             }  
  53.         }  
  54.     }     
  55.     return 0;  
  56. }  
  57.   
  58. int main(){  
  59.       
  60.     freopen(”grid.in”,“r”,stdin);  
  61.     freopen(”grid.out”,“w”,stdout);   
  62.       
  63.     memset(head,-1,sizeof head);  
  64.     scanf(”%d%d”,&m,&n);  
  65.     for(int i=1;i<=m;i++)  
  66.         for(int j=1;j<=n;j++)  
  67.             scanf(”%d”,&map[i][j]);  
  68.     for(int i=1;i<=m;i++)  
  69.         for(int j=1;j<=n;j++){  
  70.             if(!((i+j)&1)){  
  71.                 add(ss,PLA(i,j),map[i][j]);  
  72.                 if(i+1<=m)add(PLA(i,j),PLA(i+1,j),INF);  
  73.                 if(j+1<=n)add(PLA(i,j),PLA(i,j+1),INF);  
  74.                 if(i-1>=1)add(PLA(i,j),PLA(i-1,j),INF);  
  75.                 if(j-1>=1)add(PLA(i,j),PLA(i,j-1),INF);  
  76.             }  
  77.             else  
  78.                 add(PLA(i,j),tt,map[i][j]);  
  79.             sum+=(map[i][j]);  
  80.         }  
  81.     int flag,weight=0;  
  82.     while(BFS())  
  83.         while(flag=dfs(ss,INF))weight+=flag;  
  84.     printf(”%d\n”,sum-weight);  
  85.     return 0;  
  86. }  
1 0