poj 3422:Kaka's Matrix Travels(最小费用最大流)
来源:互联网 发布:java ftp删除文件 编辑:程序博客网 时间:2024/05/11 13:05
大致题意:
给出N和K,表示一个N*N个区域组成的的方阵map,方阵的每个区域都有自己的一个值map[i][j]。现从(0,0)点走到(n,n)点走K次,规定只能向右走或者向下走,每经过一个区域取走区域中的值,map[i][j]变为0,一个区域可以被多次经过。求最多能取走多少值。
大致思路:
最小费用最大流。说实话一直觉得这道题算法叫最大费用最大流更合适,因为这里求的是取走费用总和的最大值。但是终归还是要用费用流的模版,毕竟只是最小费用流模版改了几个小地方而已。
建图方案。因为这里并不规定一个区域最多走多少次,但是能获得其上面数字map[i][j]的次数只有一次,所以这里可以将一个点拆作两个点再用两条边连接他们。一条的流量是1费用是map[i][j],代表能得到收入map[i][j]的次数只有一次。另一条流量是inf费用是0,代表这个点可以被0收入地经过无数次。再将其拆出的第二个点与其下方和右方的点连上一条边,流量为inf费用为0。设一个超级原点0连接1,这条边流量是K,费用是0。然后对构造出的图从0到第2*N*N个点使用最小费用最大流模版。
说到模版,本来想带poj 2135的模版来用,没想到tle了,最后看大牛的博客说在用spfa时使用堆栈会超时,换队列的spfa模版过了。哪位大牛知道这是为何的话麻烦帮忙给我解释解释啊。
给出N和K,表示一个N*N个区域组成的的方阵map,方阵的每个区域都有自己的一个值map[i][j]。现从(0,0)点走到(n,n)点走K次,规定只能向右走或者向下走,每经过一个区域取走区域中的值,map[i][j]变为0,一个区域可以被多次经过。求最多能取走多少值。
大致思路:
最小费用最大流。说实话一直觉得这道题算法叫最大费用最大流更合适,因为这里求的是取走费用总和的最大值。但是终归还是要用费用流的模版,毕竟只是最小费用流模版改了几个小地方而已。
建图方案。因为这里并不规定一个区域最多走多少次,但是能获得其上面数字map[i][j]的次数只有一次,所以这里可以将一个点拆作两个点再用两条边连接他们。一条的流量是1费用是map[i][j],代表能得到收入map[i][j]的次数只有一次。另一条流量是inf费用是0,代表这个点可以被0收入地经过无数次。再将其拆出的第二个点与其下方和右方的点连上一条边,流量为inf费用为0。设一个超级原点0连接1,这条边流量是K,费用是0。然后对构造出的图从0到第2*N*N个点使用最小费用最大流模版。
说到模版,本来想带poj 2135的模版来用,没想到tle了,最后看大牛的博客说在用spfa时使用堆栈会超时,换队列的spfa模版过了。哪位大牛知道这是为何的话麻烦帮忙给我解释解释啊。
详细代码:
#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int inf=99999999;const int nMax=5005;struct{ int v, cap, cost, next, re;}edge[40005];int n,m,ans;int k,edgeHead[nMax];int que[5005],pre[5005],dis[5005];bool vis[5005];void addEdge(int u,int v,int ca,int co){ edge[k].v=v; edge[k].cap=ca; edge[k].cost=co; edge[k].next=edgeHead[u]; edge[k].re=k + 1; edgeHead[u]=k ++; edge[k].v=u; edge[k].cap=0; edge[k].cost=-co; edge[k].next=edgeHead[v]; edge[k].re=k - 1; edgeHead[v]=k ++;}bool spfa(){ int i, head = 0, tail = 1; // 长注释的地方就是从最小费用改到最大费用时需要变动的地方 for(i = 0; i <= n; i ++){ dis[i] = -1;//////////// vis[i] = false; } dis[0] = 0; que[0] = 0; vis[0] = true; while(head != tail){ int u = que[head]; for(i = edgeHead[u]; i != 0; i = edge[i].next){ int v = edge[i].v; if(edge[i].cap && dis[v] <dis[u] + edge[i].cost){//////// dis[v] = dis[u] + edge[i].cost; pre[v] = i; if(!vis[v]){ vis[v] = true; que[tail ++] = v; if(tail == 5005) tail = 0; } } } vis[u] = false; head++; if(head ==5005) head = 0; } if(dis[n] ==-1) return false;/////////// return true;}void end(){ int u, p; for(u = n; u != 0; u = edge[edge[p].re].v){ p = pre[u]; edge[p].cap -= 1; edge[edge[p].re].cap += 1; ans += edge[p].cost; }}int main(){ int map[60][60]; int a,b,c,d,i,j,N,K; k=1; memset(edgeHead,0,sizeof(edgeHead)); memset(vis,0,sizeof(vis)); scanf("%d%d",&N,&K); for(i=1;i<=N;i++){ for(j=1;j<=N;j++){ scanf("%d",&map[i][j]); } } addEdge(0,1,K,0); for(i=1;i<=N;i++){ for(j=1;j<=N;j++){ a=(i-1)*N+j; a=a*2-1; b=a+1; addEdge(a,b,1,map[i][j]); addEdge(a,b,K,0); if(i<N)addEdge(b,a+2*N,K,0); if(j<N)addEdge(b,b+1,K,0); } } n=2*N*N; ans=0; while(spfa())end(); cout<<ans<<endl; return 0;}
- poj 3422 Kaka's Matrix Travels 最小费用最大流
- poj-3422-Kaka's Matrix Travels-最小费用最大流
- POJ 3422 Kaka's Matrix Travels 最小费用最大流
- poj 3422 Kaka's Matrix Travels(最小费用最大流)
- POJ Kaka's Matrix Travels 3422 (最小费用最大流)
- POJ 3422 Kaka's Matrix Travels (最小费用流)
- poj 3422 Kaka's Matrix Travels(最小费用流)
- poj 3422:Kaka's Matrix Travels(最小费用最大流)
- poj 3422 Kaka's Matrix Travels(最小费用最大流)
- POJ 3422 Kaka's Matrix Travels (最小费用最大流)
- poj 3422 Kaka's Matrix Travels(最小费用最大流)
- 【POJ 3422】 Kaka's Matrix Travels (最小费用最大流)
- POJ 3422 Kaka's Matrix Travels (最大费用最大流)
- POJ 3422 Kaka's Matrix Travels (最大费用最大流)
- 【最大费用最大流】POJ-3422 Kaka's Matrix Travels
- POJ 3422 Kaka's Matrix Travels 最大费用最大流
- POJ Kaka's Matrix Travels (最大费用最大流)
- POJ 3422 Kaka's Matrix Travels 最小费用流
- Android的RIL驱动模块启动流程
- Android开发知识:字符串资源文件format方法介绍
- flex和java交互的三种方式之一:httpService
- Android2.3 SDK编译出现Multiple substitutions specified in non-positional format的分析
- asp.net 控件的 ID ,ClientID ,UniqueID 区别
- poj 3422:Kaka's Matrix Travels(最小费用最大流)
- C++中常见的内存错误
- 关于做Android+J2ee系统集成开发的一点心得
- 20110905晴 每日英语
- VS快捷键
- JIRA has been locked
- Java HttpURLConnection超时问题
- pku acm 1017
- 最近发现一些double不能做金融计算的问题