您的位置:首页 > 理论基础 > 计算机网络

POJ 3422 Kaka's Matrix Travels 解题报告(最大费用最大流)

2013-08-12 18:46 417 查看
    题目大意:矩阵中每次只能向下走或者向右走。走K次问能得到的最大的和是多少。

    解题报告:一开始以为是普通的贪心,每次取上边或者是左边中较大的数,取K次。当然,WA了。Discuss里也有讨论,例如下面这种情况:

    1  1  0

    4  3  3

    5  0  1

    贪心的话,第一次取 1,4,3,3,1,第二次取5。当然,最优解是取1,1,3,3,1,和4,5。

    当然,这种情况实在不知道怎么做,那就搜吧。学习了最小费用最大流。

    所谓最小费用最大流,即每次选择费用最小的增广路径进行增广,直到没有增广路径为止。

    寻找最小路径可以用最短路算法。因为可能有负权边,所以使用Bellman算法或者SPFA。

    最小费用最大流与最大费用最大流实际上是一样的。本题求的是最大费用最大流。

    注意建图。要拆点。

    代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int n,ans;
const int maxV=5010;
const int maxE=20010;
int first[maxV],vv[maxE],cap[maxE],cost[maxE],nxt[maxE];
int dis[maxV],pre[maxV],que[maxV];
bool vis[maxV];

bool spfa()
{
memset(dis,-1,sizeof(dis));
memset(vis,0,sizeof(vis));

int top=1,bot=0;
que[0]=0;
vis[0]=true;
dis[0]=0;

while(top!=bot)
{
int u=que[bot++];
if(bot==maxV) bot=0;
vis[u]=false;

for(int e=first[u];e;e=nxt[e])
if(cap[e] && dis[vv[e]]<dis[u]+cost[e])
{
int v=vv[e];
dis[v]=dis[u]+cost[e];
pre[v]=e;
if(!vis[v])
{
vis[v]=true;
que[top++]=v;
if(top==maxV) top=0;
}
}
}

return dis
>0;
}

void end()
{
for(int u=n,e;u;u=vv[e^1])
{
e=pre[u];
cap[e]-=1;
cap[e^1]+=1;
ans+=cost[e];
}
}

int e=2;
void addEdge(int u,int v,int ca,int co)
{
nxt[e]=first[u],vv[e]=v,cap[e]=ca,cost[e]=co,first[u]=e++;
nxt[e]=first[v],vv[e]=u,cap[e]=0,cost[e]=-co,first[v]=e++;
}

int main()
{
int N,K;
int mp[52][52];

scanf("%d%d",&N,&K);
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
scanf("%d",&mp[i][j]);
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
{
int a=(i-1)*N+j;
int b=a+N*N;
addEdge(a,b,1,mp[i][j]);
addEdge(a,b,K,0);
if(i<N) addEdge(b,a+N,K,0);
if(j<N) addEdge(b,a+1,K,0);
}

n=2*N*N+1;
addEdge(0,1,K,0);
addEdge(n-1,n,K,0);

ans=0;
while(spfa()) end();
printf("%d\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  网络流