★ POJ 2516 最小费用最大流(分开计算,K次费用流)
来源:互联网 发布:多媒体教学软件 编辑:程序博客网 时间:2024/05/18 01:58
题意:给你m个供货源,n个店,k种商品,每个店对于每种商品的需求量以及每个供货源运送k种商品到相应店的费用,求最小费用。
分析:
1、直接暴力n*k+m*k个点建图加剪枝勉强过。
2、正解,对于每种物品,分开计算最小费用,最后相加即可。
代码1:
//O(Kn^2m)//如果要求最大费用的话 只需在加边的时候加-的边 输出时输出-ans即可#pragma comment(linker,"/STACK:102400000,102400000")#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <vector>#include <string>#include <math.h>#include <queue>#include <stack>#include <map>#include <set>using namespace std;typedef long long ll; //记得必要的时候改成无符号const int maxn=5005;const int maxm=1000005;const int INF=1000000000;struct EdgeNode{ int from; int to; int flow; int cost; int next;}edge[maxm];int head[maxn],cnt;void add(int x,int y,int z,int c){ edge[cnt].from=x;edge[cnt].to=y;edge[cnt].flow=z;edge[cnt].cost=c;edge[cnt].next=head[x];head[x]=cnt++; edge[cnt].from=y;edge[cnt].to=x;edge[cnt].flow=0;edge[cnt].cost=-c;edge[cnt].next=head[y];head[y]=cnt++;}void init(){ cnt=0; memset(head,-1,sizeof(head));}int S,T,n,m;int d[maxn],in[maxn],pre[maxn];queue<int>Q;bool spfa(int S,int T){ int u,v,f,c; while(!Q.empty())Q.pop(); memset(in,0,sizeof(in)); for(int i=0;i<=n;i++)d[i]=INF; d[S]=0; Q.push(S); while(!Q.empty()) { u=Q.front(); Q.pop(); in[u]=0; for(int i=head[u];i!=-1;i=edge[i].next){ v=edge[i].to; f=edge[i].flow; c=edge[i].cost; if(f&&d[u]+c<d[v]){ d[v]=d[u]+c; pre[v]=i; if(!in[v]){ in[v]=1; Q.push(v); } } } } if(d[T]==INF)return false; return true;}int MCMF(int S,int T,int need=0){ int u; int max_flow=0; int min_cost=0; while(spfa(S,T)) { int flow=INF; u=T; while(u!=S){ flow=min(flow,edge[pre[u]].flow); u=edge[pre[u]].from; } u=T; max_flow+=flow; min_cost+=d[T]*flow; while(u!=S){ edge[pre[u]].flow-=flow; edge[pre[u]^1].flow+=flow; u=edge[pre[u]].from; } } return min_cost;}int mp[55][55],you[55][55];int co[55][55][55],a[55],b[55];int main(){ int i,j,l,k,x,y; while(~scanf("%d%d%d",&n,&m,&k)&&(n+m+k)) { init(); S=0; T=m*k+n*k+1; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); for(i=1;i<=n;i++)for(j=1;j<=k;j++)scanf("%d",&mp[i][j]),a[j]+=mp[i][j]; for(i=1;i<=m;i++)for(j=1;j<=k;j++)scanf("%d",&you[i][j]),b[j]+=you[i][j]; for(i=1;i<=k;i++){ for(j=1;j<=n;j++){ for(l=1;l<=m;l++)scanf("%d",&co[i][j][l]); } } for(i=1;i<=k;i++)if(b[i]<a[i])break; if(i<=k){ printf("-1\n"); continue; } for(i=1;i<=m;i++){ for(j=1;j<=k;j++){ y=(i-1)*k+j; add(S,y,you[i][j],0); } } for(i=1;i<=n;i++){ for(j=1;j<=k;j++){ x=m*k+(i-1)*k+j; add(x,T,mp[i][j],0); } } for(i=1;i<=m;i++){ for(j=1;j<=k;j++){ for(l=1;l<=n;l++){ x=(i-1)*k+j; y=m*k+(l-1)*k+j; add(x,y,you[i][j],co[j][l][i]); } } } n=T+1; printf("%d\n",MCMF(S,T)); } return 0;}
代码2:
//O(Kn^2m)//如果要求最大费用的话 只需在加边的时候加-的边 输出时输出-ans即可#pragma comment(linker,"/STACK:102400000,102400000")#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <vector>#include <string>#include <math.h>#include <queue>#include <stack>#include <map>#include <set>using namespace std;typedef long long ll; //记得必要的时候改成无符号const int maxn=205;const int maxm=1000005;const int INF=1000000000;struct EdgeNode{ int from; int to; int flow; int cost; int next;}edge[maxm];int head[maxn],cnt;void add(int x,int y,int z,int c){ edge[cnt].from=x;edge[cnt].to=y;edge[cnt].flow=z;edge[cnt].cost=c;edge[cnt].next=head[x];head[x]=cnt++; edge[cnt].from=y;edge[cnt].to=x;edge[cnt].flow=0;edge[cnt].cost=-c;edge[cnt].next=head[y];head[y]=cnt++;}void init(){ cnt=0; memset(head,-1,sizeof(head));}int S,T,n,m;int d[maxn],in[maxn],pre[maxn];queue<int>Q;bool spfa(int S,int T){ int u,v,f,c; while(!Q.empty())Q.pop(); memset(in,0,sizeof(in)); for(int i=0;i<maxn;i++)d[i]=INF; d[S]=0; Q.push(S); while(!Q.empty()) { u=Q.front(); Q.pop(); in[u]=0; for(int i=head[u];i!=-1;i=edge[i].next){ v=edge[i].to; f=edge[i].flow; c=edge[i].cost; if(f&&d[u]+c<d[v]){ d[v]=d[u]+c; pre[v]=i; if(!in[v]){ in[v]=1; Q.push(v); } } } } if(d[T]==INF)return false; return true;}int MCMF(int S,int T,int need=0){ int u; int max_flow=0; int min_cost=0; while(spfa(S,T)) { int flow=INF; u=T; while(u!=S){ flow=min(flow,edge[pre[u]].flow); u=edge[pre[u]].from; } u=T; max_flow+=flow; min_cost+=d[T]*flow; while(u!=S){ edge[pre[u]].flow-=flow; edge[pre[u]^1].flow+=flow; u=edge[pre[u]].from; } } return min_cost;}int mp[55][55],you[55][55];int co[55][55][55],a[55],b[55];void build(int x){ int i,j; init(); S=0; T=n+m+1; for(i=1;i<=m;i++)add(S,i,you[i][x],0); for(i=1;i<=m;i++){ for(j=1;j<=n;j++){ add(i,m+j,you[i][x],co[x][j][i]); } } for(i=1;i<=n;i++)add(m+i,T,mp[i][x],0);}int main(){ int i,j,l,k,x,y,sum; while(~scanf("%d%d%d",&n,&m,&k)&&(n+m+k)) { init(); sum=0; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); for(i=1;i<=n;i++)for(j=1;j<=k;j++)scanf("%d",&mp[i][j]),a[j]+=mp[i][j]; for(i=1;i<=m;i++)for(j=1;j<=k;j++)scanf("%d",&you[i][j]),b[j]+=you[i][j]; for(i=1;i<=k;i++){ for(j=1;j<=n;j++){ for(l=1;l<=m;l++)scanf("%d",&co[i][j][l]); } } for(i=1;i<=k;i++)if(b[i]<a[i])break; if(i<=k){ printf("-1\n"); continue; } for(i=1;i<=k;i++){ build(i); sum+=MCMF(S,T); } printf("%d\n",sum); } return 0;}
0 0
- ★ POJ 2516 最小费用最大流(分开计算,K次费用流)
- POJ 2516 跑k次的最小费用最大流
- poj 2516 Minimum Cost(k次最小费用最大流)
- POJ 2516 最小费用流构K次图
- POJ 2516 Minimum Cost k次最小费用流
- POJ 2516(最小费用最大流)
- poj 2516(最小费用最大流)
- Minimum Cost (poj 2516 求K次最小费用流)
- poj 2516 最小费用最大流
- 【最小费用最大流】POJ 2516【unsolved】
- poj 2516 最小费用最大流
- poj 2516 最小费用最大流
- poj 2516 最小费用最大流
- POJ-2516-最小费用最大流
- poj 2159(最小费用最大流)
- poj 2195 (最小费用最大流)
- poj 2516 Minimum Cost 【最小费用最大流】【求解K种物品的最小费用,独立求解累加每个结果】
- poj 2516 Minimum Cost(最小费用最大流)
- Android中的Audio播放:竞争Audio之Audio Focus的应用
- [JIRA] Jira中文乱码问题以及自动备份
- HDU_ACM-2039 三角形
- Python的MD5和SHA
- 树状数组
- ★ POJ 2516 最小费用最大流(分开计算,K次费用流)
- Android中的Audio播放:音量和远程播放控制
- 黑马程序员-File及其操作
- Android数据库高手秘籍(一)——SQLite命令
- intellij背景护眼色调节
- Android MediaPlayer状态机
- 过滤器
- 小白书41页最长回文字串
- 23种设计模式