您的位置:首页 > 理论基础 > 计算机网络

网络流(最大流) HDU 1565 方格取数(1) HDU 1569 方格取数(2)

2016-02-28 15:39 579 查看
HDU 1565 方格取数(1)
给你一个n*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。

Input

包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=20)

Output

对于每个测试实例,输出可能取得的最大的和

Sample Input

3
75 15 21
75 15 28
34 70 5

Sample Output

188
直接用这个程序拿双倍经验吧~


#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>

using namespace std;
const int INF=2147483647;
const int maxn=10010,maxm=1000010;
int cnt,fir[maxn],nxt[maxm],cap[maxm],to[maxm],dis[maxn],gap[maxn],path[maxn];
int map[53][53];
void addedge(int a,int b,int c)
{
nxt[++cnt]=fir[a];
to[cnt]=b;
cap[cnt]=c;
fir[a]=cnt;
}

bool BFS(int S,int T)
{
memset(dis,0,sizeof(dis));
dis[T]=1;
queue<int>q;q.push(T);
while(!q.empty())
{
int node=q.front();q.pop();
for(int i=fir[node];i;i=nxt[i])
{
if(dis[to[i]])continue;
dis[to[i]]=dis[node]+1;
q.push(to[i]);
}
}
return dis[S];
}
int fron[maxn];
int ISAP(int S,int T)
{
if(!BFS(S,T))
return 0;
for(int i=1;i<=T;i++)++gap[dis[i]];
int p=S,ret=0;
memcpy(fron,fir,sizeof(fir));
while(dis[S]<=T)
{
if(p==T){
int f=INF;
while(p!=S){
f=min(f,cap[path[p]]);
p=to[path[p]^1];
}
p=T;ret+=f;
while(p!=S){
cap[path[p]]-=f;
cap[path[p]^1]+=f;
p=to[path[p]^1];
}
}
int &ii=fron[p];
for(;ii;ii=nxt[ii]){
if(!cap[ii]||dis[to[ii]]+1!=dis[p])
continue;
else
break;
}
if(ii){
p=to[ii];
path[p]=ii;
}
else{
if(--gap[dis[p]]==0)break;
int minn=T+1;
for(int i=fir[p];i;i=nxt[i])
if(cap[i])
minn=min(minn,dis[to[i]]);
gap[dis[p]=minn+1]++;
fron[p]=fir[p];
if(p!=S)
p=to[path[p]^1];
}
}
return ret;
}

void Init()
{
memset(fir,0,sizeof(fir));
memset(gap,0,sizeof(gap));
cnt=1;
}

int n,m;

int dot(int x,int y){
return (x-1)*m+y;
}

int main()
{
int sum;
while(~scanf("%d%d",&n,&m))
{
Init();sum=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("%d",&map[i][j]);
sum+=map[i][j];
}

for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if((i+j)%2==1){
addedge(0,(i-1)*m+j,map[i][j]);
addedge((i-1)*m+j,0,0);
}

for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if((i+j)%2==0){
addedge((i-1)*m+j,n*m+1,map[i][j]);
addedge(n*m+1,(i-1)*m+j,0);
}

for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if((i+j)%2==1){
if(i+1<=n){
addedge(dot(i,j),dot(i+1,j),INF);
addedge(dot(i+1,j),dot(i,j),0);
}
if(i-1>=1){
addedge(dot(i,j),dot(i-1,j),INF);
addedge(dot(i-1,j),dot(i,j),0);
}if(j-1>=1){
addedge(dot(i,j),dot(i,j-1),INF);
addedge(dot(i,j-1),dot(i,j),0);
}
if(j+1<=m){
addedge(dot(i,j),dot(i,j+1),INF);
addedge(dot(i,j+1),dot(i,j),0);
}

}
printf("%d\n",sum-ISAP(0,n*m+1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: