标签:c++
题目链接:
题意:
有一个N X N的矩阵, 矩阵的每一小格都有且仅有一个数字v,kaka每经过一个数字就会把它捡起来并将那个数字加到sum上去.
现在kaka能通过向下或向右走的方式从 (1,1)到(n,n) K次,问kaka能取到的最大的sum是多少.
解题思路:
题目问题可以抽象为 求多次可走重复路的最长路的最大和问题
首先想到的就应该是最小费用最大流, 而题目要求的最大和值,那么应求就是最大费用最大流, 仅仅只需要将代码中的最小路算法改为最长路算法即可
题目的条件是能多次经过同一个点,那么应该这样建边:
将矩阵中的每个点拆成两个点 i和n*n+i,
1.建立一条 i到n*n+i 容量为1 费用为w[x][y]的边
2.再建立一条 i到n*n+i 容量为k-1 费用为0的边
3.而对于矩阵中的相邻的点i ,j 建立一条 n*n+i到j 容量为k 费用为0的边
4.最后补上源点到1 n*n*2到汇点边 进行最大费用最大流即可
其实只要将容量理解为经过次数就很好理解了.
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #define maxn 5050 using namespace std; struct node { int to,c,v,next; int f; }edge[maxn*10]; int dis[maxn]; int head[maxn],ss; int pre[maxn]; int n,s,t; int ans; void init() { memset(head,-1,sizeof(head)); ss=0; ans=0; } void addedge(int a,int b,int c,int d) { edge[ss]=(node){b,c,d,head[a],0}; head[a]=ss++; edge[ss]=(node){a,c,-d,head[b],c}; head[b]=ss++; } int spfa() { queue<int>q; int vis[maxn]={0}; memset(dis,-1,sizeof(dis)); int u,v; q.push(0); dis[0]=0; while(!q.empty()) { u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];i!=-1;i=edge[i].next) { v=edge[i].to; if(edge[i].c-edge[i].f>0&&dis[v]<dis[u]+edge[i].v) //最长路 改符号即可 { dis[v]=dis[u]+edge[i].v; pre[v]=i; if(!vis[v]) { vis[v]=1; q.push(v); } } } } if(dis[t]>0) return 1; return 0; } void MCMF() { int min_f; while(spfa()) { min_f=105; for(int i=t;i!=s;i=edge[pre[i]^1].to){ edge[pre[i]].f+=1; //本应该统计可增广的最大流 edge[pre[i]^1].f-=1; //但题目条件特殊 -1即可 } ans+=dis[t]; } } int main() { // freopen("in.txt","r",stdin); int w[105][105]; int k,d1,d2; int i2,j2; while(~scanf("%d%d",&n,&k)) { init(); s=0,t=n*n*2+1; addedge(s,1,k,0); // 4 addedge(n*n*2,t,k,0); // 4 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&w[i][j]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { d1=(i-1)*n+j+n*n; addedge(d1-n*n,d1,1,w[i][j]); // 1 addedge(d1-n*n,d1,k-1,0); // 2 i2=i+1,j2=j; if(i2>=1&&i2<=n&&j2>=1&&j2<=n){ d2=(i2-1)*n+j2; addedge(d1,d2,k,0); // 3 } i2=i,j2=j+1; if(i2>=1&&i2<=n&&j2>=1&&j2<=n){ d2=(i2-1)*n+j2; addedge(d1,d2,k,0); // 3 } } MCMF(); printf("%d\n",ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
POj3422 Kaka's Matrix Travels 最小费用最大流 拆点
标签:c++
原文地址:http://blog.csdn.net/axuan_k/article/details/47335965