POJ3422 Kaka's Matrix Travels(最大费用最大流 + 拆点)
来源:互联网 发布:充值管理系统 源码 编辑:程序博客网 时间:2024/04/28 06:13
题目链接:http://poj.org/problem?id=3422
题意:有一个n*n的矩阵,格子中的元素是费用,KaKa从左上角开始出发要到达右下角,但是他只能向下走或者向右走,且走过的格子赋值为0,可以走K次,问K次后KaKa能获得的最大费用是多少?
思路:首先解释一下为什么要拆点?
因为要获得最大费用,所以假设当前步选择先下走,最终得到的结果可能不是最大值,但根据题意却把走过的格子赋为0了,这就影响了最终结果。所以进行拆点,把每个点拆成两个点,入度点和出度点,本点的入度点连接着本点的出度点,费用为本点格子的值的负值,容量为1(因为当前点的入度点只能由(上边点)/(左边点)的出度点连接,所以容量是1),这样使用流网络就保证了最终的结果不受一些不是最优解的中间过程的影响。而当前点的出度点连接下个点的入度点的费用为0,容量为K,因为可以走K次,所以在走过一次后,费用已经赋为0,容量就变成K-1,谁走进当前格子,对整体的费用已经没有影响了。
再建立一个源点和一个汇点,源点与1点(左上角)相连费用0,容量K,汇点与2*n*n+1点(右下角)相连费用0,容量为K
求最大费用最大流,可以再建图的时候把费用改为负值,在求最小费用最大流,也可以再SPFA中改最长路,直接求最大费用最大流
第一种
#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>const int maxn = 20000;const int maxm = 800000;const int inf = 1e8;#define MIN INT_MIN#define MAX 1e6#define LL long long#define init(a) memset(a,0,sizeof(a))#define FOR(i,a,b) for(int i = a;i<b;i++)#define max(a,b) (a>b)?(a):(b)#define min(a,b) (a>b)?(b):(a)using namespace std;struct node{ int u,v,w,cap,next;} edge[maxm];int pre[maxn],dis[maxn],head[maxn],cnt;bool vis[maxn];int n;void add(int u,int v,int c,int cap){ edge[cnt].u=u; edge[cnt].v=v; edge[cnt].w=c; edge[cnt].cap=cap; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].u=v; edge[cnt].v=u; edge[cnt].w=-c; edge[cnt].cap=0; edge[cnt].next=head[v]; head[v]=cnt++;}int spfa(int s,int t){ queue<int>q; while(q.empty()==false) q.pop(); q.push(s); memset(vis,0,sizeof(vis)); memset(pre,-1,sizeof(pre)); FOR(i,s,t+1) dis[i] = inf; dis[s]=0; while(!q.empty()) { int u=q.front(); q.pop(); vis[u] = 0; for(int i=head[u]; i!=-1; i=edge[i].next) { if(edge[i].cap && dis[edge[i].v]>dis[u]+edge[i].w) { dis[edge[i].v]=dis[u]+edge[i].w; pre[edge[i].v] = i; if(!vis[edge[i].v]) { vis[edge[i].v]=1; q.push(edge[i].v); } } } } if(dis[t] != inf) return 1; else return 0;}int MinCostMaxFlow(int s,int t){ int flow=0,cost=0; while(spfa(s,t)) { int df = inf; for(int i = pre[t]; i!=-1; i=pre[edge[i].u]) { if(edge[i].cap<df) df = edge[i].cap; } flow += df; for(int i=pre[t]; i!=-1; i=pre[edge[i].u]) { edge[i].cap -= df; edge[i^1].cap += df; } //printf("df = %d\n",df); cost += dis[t] * df; } return cost;}void initt(){ cnt=0; memset(head,-1,sizeof(head));}int ma;int main(){ int s,t,k; while(~scanf("%d%d",&n,&k)) { initt(); s = 0; t=2*n*n+1; add(s,1,0,k); int num = n*n; FOR(i,1,n+1) { FOR(j,1,n+1) { scanf("%d",&ma); add((i-1)*n+j,(i-1)*n+j+num,-ma,1); add((i-1)*n+j,(i-1)*n+j+num,0,k-1); if(i<=n-1)//向下建图 { add((i-1)*n+j+num,i*n+j,0,k); } if(j<=n-1)//向右建图 { add((i-1)*n+j+num,(i-1)*n+j+1,0,k); } } } add(t-1,t,0,k); int ans = MinCostMaxFlow(s,t); cout<<abs(ans)<<endl; } return 0;}
求最长路的最大费用最大流
#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>const int maxn = 20000;const int maxm = 800000;const int inf = 1e8;const int INF = 0x3f3f3f3f;#define MIN INT_MIN#define MAX 1e6#define LL long long#define init(a) memset(a,0,sizeof(a))#define FOR(i,a,b) for(int i = a;i<b;i++)#define max(a,b) (a>b)?(a):(b)#define min(a,b) (a>b)?(b):(a)using namespace std;struct node{ int u,v,w,cap,next;} edge[maxm];int pre[maxn],dis[maxn],head[maxn],cnt;bool vis[maxn];int n;void add(int u,int v,int c,int cap){ edge[cnt].u=u; edge[cnt].v=v; edge[cnt].w=c; edge[cnt].cap=cap; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].u=v; edge[cnt].v=u; edge[cnt].w=-c; edge[cnt].cap=0; edge[cnt].next=head[v]; head[v]=cnt++;}int spfa(int s,int t){ queue<int>q; while(q.empty()==false) q.pop(); q.push(s); memset(vis,0,sizeof(vis)); memset(pre,-1,sizeof(pre)); FOR(i,s,t+1) dis[i] = -1;//求最长路dis数组初始化为-1 dis[s]=0; vis[s] = 1; while(!q.empty()) { int u=q.front(); q.pop(); vis[u] = 0; for(int i=head[u]; i!=-1; i=edge[i].next) { if(edge[i].cap && dis[edge[i].v] < (dis[u]+edge[i].w))//求最长路 { dis[edge[i].v] = dis[u]+edge[i].w; pre[edge[i].v] = i; if(!vis[edge[i].v]) { vis[edge[i].v]=1; q.push(edge[i].v); } } } } if(dis[t] != -1)//------------------忘改了。。 return 1; else return 0;}int MinCostMaxFlow(int s,int t){ int flow=0,cost=0; while(spfa(s,t)) { int df = inf; for(int i = pre[t]; i!=-1; i=pre[edge[i].u]) { if(edge[i].cap<df) df = edge[i].cap; } flow += df; for(int i=pre[t]; i!=-1; i=pre[edge[i].u]) { edge[i].cap -= df; edge[i^1].cap += df; } //printf("df = %d\n",df); cost += dis[t] * df; } return cost;}void initt(){ cnt=0; memset(head,-1,sizeof(head));}int ma;int main(){ int s,t,k; while(~scanf("%d%d",&n,&k)) { initt(); s = 0; t=2*n*n+1; add(s,1,0,k); int num = n*n; FOR(i,1,n+1) { FOR(j,1,n+1) { scanf("%d",&ma); add((i-1)*n+j,(i-1)*n+j+num,ma,1); add((i-1)*n+j,(i-1)*n+j+num,0,k-1);//本点与拆点连线,费用0 if(i<=n-1)//向下建图 { add((i-1)*n+j+num,i*n+j,0,k); } if(j<=n-1)//向右建图 { add((i-1)*n+j+num,(i-1)*n+j+1,0,k); } } } add(t-1,t,0,k); int ans = MinCostMaxFlow(s,t); printf("%d\n",ans); } return 0;}
0 0
- poj3422--Kaka's Matrix Travels(拆点,最大费用)
- POJ3422 Kaka's Matrix Travels(最大费用最大流 + 拆点)
- poj3422 Kaka's Matrix Travels 最大费用最大流
- poj3422 Kaka's Matrix Travels 最大费用最大流
- POJ3422 Kaka's Matrix Travels 【最大费用最大流】
- poj3422 Kaka's Matrix Travels 最大费用流 (拆点)
- POj3422 Kaka's Matrix Travels 最小费用最大流 拆点
- poj3422 Kaka's Matrix Travels 拆点+费用流
- POJ3422 Kaka's Matrix Travels 拆点+费用流(SPFA)
- 费用流 poj3422 Kaka's Matrix Travels
- POJ3422 Kaka's Matrix Travels(费用流)
- Kaka's Matrix Travels (最大费用流)
- 【最大费用流】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(最大费用流,巧妙构图,拆点)
- 匹配form表单中所有内容的正则表达式
- android onCreateOptionMenu的使用
- 简介客户关系管理
- Disable MySQL Foreign Key During JUnit Test
- 甲骨文Dynamics GP的大平原整合注意事项
- POJ3422 Kaka's Matrix Travels(最大费用最大流 + 拆点)
- 环球鞋每个女人
- cocos2dx中retain和release
- 互联网最值得关注的十大微信号(最新)
- 黑马程序员--致黑马训练营的一封感谢信
- LLDPE保税交割顺利完成啦
- 火麻仁鲤鱼饵,最终上瘾的鱼饵
- Linux命令 之 free (buffer与cache区别 )
- 如何在批处理中调用多个批处理?