方格取数(2)
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6000 Accepted Submission(s): 1908
Problem Description
给你一个m*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的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
思路
1、首先,这个题是一个二分图模型。并且我们知道最大权独立集=总权-最小割=总权-最大流。
2、那么我们就在以上基础建图。
①我们将点分成两个集合,i+j为偶数的点我们规定为一个集合,那么i+j为奇数的点就是另一个集合。
②源点S和i+j为偶数的点都进行建边,其容量为a【i】【j】,i+j为奇数的点和汇点t都进行建边,其容量也是a【i】【j】;
③将i+j为偶数的点和周围四个点进行建边,其容量为无穷大。
3、求一遍最大流,其解为:总权-最大流、
Ac代码:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<string.h>
using namespace std;
int head[2550];
struct node
{
int from,to,w,next;
}e[2550*2550];
int vis[2550];
int pre[255000];
int a[55][55];
int fx[4]={0,0,1,-1};
int fy[4]={1,-1,0,0};
int n,m,s,t,sum,cont;
void add(int from,int to,int w)
{
e[cont].from=from;
e[cont].to=to;
e[cont].w=w;
e[cont].next=head[from];
head[from]=cont++;
e[cont].from=to;
e[cont].to=from;
e[cont].w=0;
e[cont].next=head[to];
head[to]=cont++;
}
int Ek_Bfs(int start,int end)
{
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));
vis[start]=1;
queue<int >s;
s.push(start);
while(!s.empty())
{
int u=s.front();
if(u==end)return 1;
s.pop();
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(vis[v]==0&&e[i].w>0)
{
vis[v]=1;
pre[v]=i;
s.push(v);
}
}
}
return 0;
}
void Edmond_Karp()
{
int maxflow=0;
int minn;
while(Ek_Bfs(s,t))
{
minn=0x3f3f3f3f;
int u=t;
while(u!=s)
{
minn=min(e[pre[u]].w,minn);
u=e[pre[u]].from;
}
u=t;
while(pre[u]!=-1)
{
e[pre[u]].w-=minn;
e[pre[u]^1].w+=minn;
u=e[pre[u]].from;
}
maxflow+=minn;
}
printf("%d\n",sum-maxflow);
}
void getmap()
{
cont=0;
memset(head,-1,sizeof(head));
s=n*m+1;
t=n*m+2;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if((i+j)%2==0)
{
add(s,(i-1)*m+j,a[i][j]);
}
else
{
add((i-1)*m+j,t,a[i][j]);
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if((i+j)%2==0)
{
for(int k=0;k<4;k++)
{
int tmpx=i+fx[k];
int tmpy=j+fy[k];
if(tmpx>=1&&tmpx<=n&&tmpy>=1&&tmpy<=m)
{
add((i-1)*m+j,(tmpx-1)*m+tmpy,0x3f3f3f3f);
}
}
}
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
sum=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
sum+=a[i][j];
}
}
getmap();
Edmond_Karp();
}
}