POJ - 2516 Minimum Cost 费用流,拆图
发布日期:2021-05-10 11:28:37 浏览次数:17 分类:精选文章

本文共 2797 字,大约阅读时间需要 9 分钟。

题目链接

题意

n个店铺,从m个市场进货,k种货物。给定市场k种货物存量,店铺k种货物需求,运输花费,问是否能满足要求,最小花费是多少

思路

费用流没得跑,就看如何建图

我一开始是一次性建图,出现以下几个问题

  • 点编号太难了,一一对应很费脑子
  • 边太多了,MCMF超时

看别的博客知道了要拆成k张图,对k种货物一一处理。因为我们需要满足所有需求,也就是必须满流,所以可以独立得拆成k张图,拆了之后发现建图简单了一个量级,按部就班建图就可以了

数据

来源POJ讨论区,感谢前辈们提供数据

input

1 3 3

1 1 1
0 1 1
1 2 2
1 0 1
1 2 3
1 1 1
2 1 1

1 1 1

3
2
20

2 4 3

0 2 3
2 3 4
1 0 2
1 0 3
0 2 4
2 3 0
2 3 1 2
1 2 3 1
1 1 2 3
2 1 3 1
2 2 3 1
2 3 4 1

2 2 1

1 1 1 1
1 2 2 100

2 4 5

2 1 2 2 2
1 1 1 2 1
2 2 2 2 2
2 1 2 1 1
2 2 2 2 1
1 2 2 2 1
1 1 6 7
5 5 2 9
4 6 6 9
9 1 9 1
7 4 1 7
4 4 7 3
5 4 7 7
9 1 3 8
8 8 2 7
1 4 7 1

1 2 3

1 1 2
2 2 1
2 1 1
7 4
4 1
7 3
0 0 0

output:

4

-1
27
4
38
15

代码

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);#define endl "\n"//#define int long longusing namespace std; typedef long long ll; const int maxn=55*55; const int maxe=500005; const int inf=0x3f3f3f3f; int n,m,k,s,t,cnt; int head[maxn]; struct Edge{ int v,w,next,flow; }edge[maxe]; int dis[maxn],incf[maxn],pre[maxn];//incf最小流量 bool inque[maxn]; int maxflow,mincost; //费用流模版 void init(){ memset(head,-1,sizeof(head)); maxflow=mincost=0; cnt=0; } void add(int u,int v,int flow,int cost){ //cout<
<<" "<
<<" "<
<<" "<
<
q; memset(dis,0x3f,sizeof(dis)); memset(inque,0,sizeof(inque)); q.push(s); dis[s]=0; inque[s]=1; incf[s]=inf; while(q.size()){ int u=q.front();q.pop(); inque[u]=0; for(int i=head[u];~i;i=edge[i].next){ if(!edge[i].flow) continue; int v=edge[i].v; if(dis[v]>dis[u]+edge[i].w){ dis[v]=dis[u]+edge[i].w; incf[v]=min(incf[u],edge[i].flow); pre[v]=i; if(!inque[v]){ q.push(v); inque[v]=1; } } } } if(dis[t]==inf) return 0; return 1; } void MCMF(){ while(spfa()){ int x=t; maxflow+=incf[t]; mincost+=dis[t]*incf[t]; int i; while(x!=s){ i=pre[x]; edge[i].flow-=incf[t]; edge[i^1].flow+=incf[t]; x=edge[i^1].v; } } } int dian[55][55];//dian i j i店j货物所需 int ku[55][55];//ku i j i库j货物拥有 int val[55][55][55];//val w i j w货物从j库到i店所需 signed main(){ while(scanf("%d%d%d",&n,&m,&k)==3){ int ans=0; if(!n&&!m&&!k) break; for(int i=1;i<=n;i++){ for(int j=1;j<=k;j++){ scanf("%d",&dian[i][j]); } } for(int i=1;i<=m;i++){ for(int j=1;j<=k;j++) scanf("%d",&ku[i][j]); } for(int w=1;w<=k;w++){ for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&val[w][i][j]); } for(int _=1;_<=k;_++){ int need=0; init(); s=n*m+1000,t=s+1; //向汇点连边 for(int i=1;i<=n;i++){ need+=dian[i][_]; add(i,t,dian[i][_],0); add(t,i,0,0); } //源点连边 for(int i=1;i<=m;i++){ add(s,i+n,ku[i][_],0); add(i+n,s,0,0); } //市场-店面 for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ add(n+j,i,ku[j][_],val[_][i][j]); add(i,n+j,0,-val[_][i][j]); } } MCMF(); if(maxflow!=need){ //满足不了 ans=-1; break; } else ans+=mincost; } printf("%d\n",ans); } }
上一篇:POJ - 1459 Power Network 最大流模版,有点意思的输入
下一篇:POJ - 2195 Going Home 费用流+BFS

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2025年04月19日 15时18分52秒