Description
在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。对于给定的方格棋盘,按照取数要求编程找出总和最大的数。
Input
第 1 行有 2 个正整数 m 和 n,分别表示棋盘的行数和列数。接下来的 m 行,每行有 n 个正整数,表示棋盘方格中的数。
Output
程序运行结束时,将取数的最大总和输出
Sample Input
3 3
1 2 3
3 2 3
2 3 1
Sample Output
11
Hint
m,n<=100
题解
因为相邻两个数不能同时取的题设要求,像国际象棋棋盘一样染色 得到二分图
然后S向每个黑点连边,容量为点权
每个白点向T连边,容量为点权
最后每个黑点到能到的白点(上下左右)连边,容量为INF(表示这些边中需要割掉一些)
最后跑一遍最大流 利用最大流最小割定理可得此为最小割(最少要割掉的点权) ans=总点权-最小割
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<queue> 2 #include<cmath> 3 #include<cstdio> 4 #include<cstring> 5 #include<iostream> 6 using namespace std; 7 const int INF=99999999; 8 struct emm{ 9 int e,f,v; 10 }a[1000007]; 11 int h[10007]; 12 int tot=1; 13 void con(int x,int y,int l) 14 { 15 if(y==-1)return; 16 a[++tot].f=h[x]; 17 h[x]=tot; 18 a[tot].e=y; 19 a[tot].v=l; 20 a[++tot].f=h[y]; 21 h[y]=tot; 22 a[tot].e=x; 23 return; 24 } 25 int tu[107][107]; 26 int num[107][107]; 27 queue<int>q; 28 int d[10007]; 29 int m,n,s,t; 30 bool bfs() 31 { 32 memset(d,0,sizeof(d)); 33 d[s]=1; 34 q.push(s); 35 while(!q.empty()) 36 { 37 int x=q.front();q.pop(); 38 for(int i=h[x];i;i=a[i].f) 39 if(!d[a[i].e]&&a[i].v) 40 { 41 d[a[i].e]=d[x]+1; 42 q.push(a[i].e); 43 } 44 } 45 return d[t]; 46 } 47 int dfs(int x,int al) 48 { 49 if(x==t||!al)return al; 50 int fl=0; 51 for(int i=h[x];i;i=a[i].f) 52 if(d[a[i].e]==d[x]+1&&a[i].v) 53 { 54 int f=dfs(a[i].e,min(a[i].v,al)); 55 if(f) 56 { 57 fl+=f; 58 al-=f; 59 a[i].v-=f; 60 a[i^1].v+=f; 61 if(!al)break; 62 } 63 } 64 if(!fl)d[x]=-1; 65 return fl; 66 } 67 int main() 68 { 69 scanf("%d%d",&m,&n); 70 s=0,t=m*n+1; 71 int sum=0; 72 for(int i=1;i<=m;++i) 73 for(int j=1;j<=n;++j) 74 { 75 scanf("%d",&tu[i][j]); 76 sum+=tu[i][j]; 77 } 78 memset(num,-1,sizeof(num)); 79 int tim=0; 80 for(int i=1;i<=m;++i) 81 for(int j=1;j<=n;++j) 82 num[i][j]=++tim; 83 for(int i=1;i<=m;++i) 84 for(int j=1;j<=n;++j) 85 if((i+j)%2==0)con(num[i][j],t,tu[i][j]); 86 else 87 { 88 con(s,num[i][j],tu[i][j]); 89 con(num[i][j],num[i-1][j],INF); 90 con(num[i][j],num[i+1][j],INF); 91 con(num[i][j],num[i][j-1],INF); 92 con(num[i][j],num[i][j+1],INF); 93 } 94 int ans=0; 95 while(bfs())ans+=dfs(s,INF); 96 cout<<sum-ans; 97 return 0; 98 }