您的位置:首页 > 其它

POJ2516 Minimum Cost 最大流最小费用典型题目

2011-09-19 22:40 281 查看
刚接触spfa算法。

我的理解是spfa算法实质是bellman算法的改进版,可以处理负值,这是和dij的本质区别,也是这里不能用dij的原因。

spfa算法的队列的大小一定要注意!开小了悲情无限。

而最大流最小费用的思路说简单了就是最大流的实现时,以前没有最小费用这个约束的时候,我们很随意的可以直接用bfs来搜索增广路径来解最大流。

但此时有最小费用这个约束。我们用最短路来搜索增广路径。

这样来求得的最大流则满足题意。

#include<iostream>

using namespace std;

int n,m,k;

const int inf=9999999;

const int N=111;

int shop

;

int storage

;

int mat

;

int cost

;

int ans;

bool visit
;

int que[N*N],pre
,dis
;//que的大小设定不是简单的N,之前在广搜的时候习惯是N,上次一题就是直接写N,就一直TLE,今天才意识到,泪流满面。

bool spfa()

{

int head=1,tail=1;

for(int i=0;i<=n+m+1;i++)

{

dis[i]=inf;

visit[i]=false;

}

dis[0]=0;

que[tail++]=0;

visit[0]=true;

while(head<tail)

{

int now=que[head++];

for(int i=0;i<=n+m+1;i++)

if(mat[now][i]>0&&dis[i]>dis[now]+cost[now][i])

{

dis[i]=dis[now]+cost[now][i];

pre[i]=now;

if(!visit[i])

{

visit[i]=true;

que[tail++]=i;

//if

}

}

visit[now]=false;

}

if(dis[n+m+1]==inf)

return false;

return true;

}

int main()

{

while(scanf("%d%d%d",&n,&m,&k),n!=0||m!=0||k!=0)

{

ans=0;

int need
;

memset(need,0,sizeof(need));

memset(shop,0,sizeof(shop));

for(int i=1;i<=n;i++)

for(int j=1;j<=k;j++)

{

scanf("%d",&shop[i][j]);

need[j]+=shop[i][j];

}

int supply
;

memset(supply,0,sizeof(supply));

memset(storage,0,sizeof(storage));

for(int i=1;i<=m;i++)

for(int j=1;j<=k;j++)

{

scanf("%d",&storage[i][j]);

supply[j]+=storage[i][j];

}

bool flag=false;

for(int i=1;i<=k;i++)

{

if(supply[i]<need[i])

{

flag=true;

break;

}

}

for(int t=1;t<=k;t++)

{

memset(mat,0,sizeof(mat));

for(int i=1;i<=n;i++)

for(int j=1;j<=m;j++)

{

scanf("%d",&cost[j][m+i]);

cost[m+i][j]=-cost[j][m+i];//这就是用spfa而不能用dij的原因

mat[j][m+i]=inf;

}

if(flag)

continue;

for(int i=1;i<=m;i++)

{

mat[0][i]=storage[i][t];

cost[0][i]=cost[i][0]=0;

}

for(int i=1;i<=n;i++)

{

mat[m+i][n+m+1]=shop[i][t];

cost[m+i][n+m+1]=cost[n+m+1][m+i]=0;

}

while(spfa())

{

int min=inf;

for(int i=m+n+1;i!=0;i=pre[i])

{

min=(min<mat[pre[i]][i]?min:mat[pre[i]][i]);

}

for(int i=n+m+1;i!=0;i=pre[i])

{

mat[pre[i]][i]-=min;

mat[i][pre[i]]+=min;

ans+=cost[pre[i]][i]*min;

}

}

}

if(flag)

printf("-1\n");

else

printf("%d\n",ans);

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: