您的位置:首页 > 其它

hdu 2686 Matrix【费用流Max_Cost_Max_flow】

2016-08-11 16:04 344 查看

Matrix

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2370    Accepted Submission(s): 1250


Problem Description

Yifenfei very like play a number game in the n*n Matrix. A positive integer number is put in each area of the Matrix.

Every time yifenfei should to do is that choose a detour which frome the top left point to the bottom right point and than back to the top left point with the maximal values of sum integers that area of Matrix yifenfei choose. But from the top to the bottom
can only choose right and down, from the bottom to the top can only choose left and up. And yifenfei can not pass the same area of the Matrix except the start and end. 

Input

The input contains multiple test cases.

Each case first line given the integer n (2<n<30) 

Than n lines,each line include n positive integers.(<100)

Output

For each test case output the maximal values yifenfei can get.

Sample Input

2

10 3

5 10

3

10 3 3

2 5 3

6 7 10

5

1 2 3 4 5

2 3 4 5 6

3 4 5 6 7

4 5 6 7 8

5 6 7 8 9

Sample Output

28

46

80

Author

yifenfei

Source

ZJFC 2009-3 Programming Contest

 

思路:

1、网络流模型,最大花费最大流。

2、首先我们需要明确这样一个问题:来回的一个最大值拿取方案,其实可以看成两次从起点走到终点的拿取方案。

3、那么我们建立网络:

①设定源点S,连入1号节点,流量为2,花费为0,表示我们两次从起点走到终点。

②对应每个点一分为二,例如:1--->1&&1'',然后我们1连入1"",其花费为其点权,流量为1,表示每个点只能拿取一次。

③设定汇点T,将n*n''连入汇点,流量为2,花费为0.

然而这样建立完图之后,发现只能跑一遍SPFA。因为我们从源点S出发,拿完了第一个节点的值之后,流变成了0,显然想找第二条增广路的时候,没有可行流了。

所以我们还要加一条:

④在1和1""以及n*n和n*n""之间多建立一条边,其花费也为点权,流量为1,这样我们跑完两次SPFA之后多加了一次1号节点和n*n号节点的权值,我们减去即可。

4、因为我们要求得到的是最大值,那么我们跑SPFA的时候就不是跑最短路了,而是跑最长路。

Ac代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<climits>
using namespace std;
#define INF 1<<28
struct node
{
int from;
int to;
int w;
int f;
int num;
int next;
}e[(610*610+2)+10];
int pre[610*61+2];
int path[610*61+2];
int vis[610*61+2];
int dis[610*61+2];
int head[610*61+2];
int que[610*61+2];
int a[65][65];
int fx[2]={1,0};
int fy[2]={0,1};
int ss,tt,cont,n;
void add(int from,int to,int w,int f)
{
e[cont].to=to;
e[cont].from=from;
e[cont].w=w;
e[cont].f=f;
e[cont].num=cont;
e[cont].next=head[from];
head[from]=cont++;
}
void getmap()
{
ss=n*n+n*n+1;
tt=ss+1;
cont=0;
memset(head,-1,sizeof(head));
add(ss,1,0,2);
add(1,ss,0,0);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==1&&j==1||i==n&&j==n)
{
add((i-1)*n+j,(i-1)*n+j+n*n,a[i][j],2);
add((i-1)*n+j+n*n,(i-1)*n+j,-a[i][j],0);
continue;
}
add((i-1)*n+j,(i-1)*n+j+n*n,a[i][j],1);
add((i-1)*n+j+n*n,(i-1)*n+j,-a[i][j],0);
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=0;k<2;k++)
{
int x=i+fx[k];
int y=j+fy[k];
if(x>=1&&x<=n&&y>=1&&y<=n)
{
int u=(i-1)*n+j;
int uu=u+n*n;
int v=(x-1)*n+y;
int vv=v+n*n;
add(uu,v,0,1);
add(v,uu,0,0);
}
}
}
}
add(n*n*2,tt,0,2);
add(tt,n*n*2,0,0);
}
int SPFA()
{
memset(que,0,sizeof(que));
memset(vis,0,sizeof(vis));
memset(path,-1,sizeof(path));
memset(pre,-1,sizeof(pre));
for(int i=1;i<=tt;i++)dis[i]=-INF;
dis[ss]=0;
vis[ss]=1;
int tot=0;
int rear=0;
que[rear++]=ss;
while(rear>tot)
{
int u=que[tot];
tot++;
vis[u]=0;
for(int i=head[u];i!=-1;i=e[i].next)
{
int w=e[i].w;
int f=e[i].f;
int v=e[i].to;
if(f>0&&dis[v]<dis[u]+w)
{
pre[v]=u;
path[v]=e[i].num;
dis[v]=dis[u]+w;
if(vis[v]==0)
{
vis[v]=1;
que[rear++]=v;
}
}
}
}
if(dis[tt]!=-INF)return 1;
else return 0;
}
void Max_costflow()
{
int ans=0,maxflow=0;
while(SPFA()==1)
{
int minn=INT_MAX;
for(int i=tt;i!=ss;i=pre[i])
{
minn=min(minn,e[path[i]].f);
}
for(int i=tt;i!=ss;i=pre[i])
{
e[path[i]].f-=minn;
e[path[i]^1].f+=minn;
}
maxflow+=minn;
ans+=dis[tt]*minn;
}
printf("%d\n",ans-a[1][1]-a

);
}
void init()
{
memset(e,0,sizeof(e));
memset(pre,-1,sizeof(pre));
memset(path,-1,sizeof(path));
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
memset(que,0,sizeof(que));
}
int main()
{
while(~scanf("%d",&n))
{
init();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&a[i][j]);
}
}
getmap();
Max_costflow();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hdu 2686 杭电 2686