标签: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