POJ 2516 费用流

题意:

有n个商店m个供应商k种商品

给各商店的各种商品的需求量和各供应商的供应量以及供应商和商店之间的运输费用,求满足需求的最小费用

题解:

很裸。很裸。。每个商品做一次最大流,就是读入我看了半天才看懂。。英语弱啊。。。

View Code
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 
  7 #define N 130
  8 #define M 100100
  9 
 10 using namespace std;
 11 
 12 int head[N],to[M],next[M],len[M],pr[M];
 13 int pre[N],n,m,p,S,T,dis[N],q[M<<4],cnt;
 14 int kr[N][N],sl[N][N],co[N][N][N],sumr,sumc;
 15 bool vis[N];
 16 
 17 inline void add(int u,int v,int r,int w)
 18 {
 19     to[cnt]=v; len[cnt]=r; pr[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
 20     to[cnt]=u; len[cnt]=0; pr[cnt]=-w; next[cnt]=head[v]; head[v]=cnt++;
 21 }
 22 
 23 inline void read()
 24 {
 25     for(int i=1;i<=n;i++)
 26         for(int j=1;j<=p;j++)
 27             scanf("%d",&kr[i][j]);
 28     for(int i=1;i<=m;i++)
 29         for(int j=1;j<=p;j++)
 30             scanf("%d",&sl[i][j]);
 31     for(int i=1;i<=p;i++)
 32         for(int j=1;j<=n;j++)
 33             for(int k=1;k<=m;k++)
 34                 scanf("%d",&co[i][j][k]);
 35 }
 36 
 37 inline void build(int u)
 38 {
 39     memset(head,-1,sizeof head); cnt=0;
 40     S=0; T=n+m+1; sumc=0;
 41     for(int i=1;i<=n;i++)
 42     {
 43         add(S,i,kr[i][u],0);
 44         sumc+=kr[i][u];
 45     }
 46     for(int i=1;i<=m;i++) add(i+n,T,sl[i][u],0);
 47     for(int i=1;i<=n;i++)
 48         for(int j=1;j<=m;j++)
 49             add(i,j+n,kr[i][u],co[u][i][j]);
 50 }
 51 
 52 inline bool spfa()
 53 {
 54     memset(dis,0x3f,sizeof dis);
 55     memset(pre,-1,sizeof pre);
 56     int h=1,t=2,sta;
 57     q[1]=S; vis[S]=true; dis[S]=0;
 58     while(h<t)
 59     {
 60         sta=q[h++]; vis[sta]=false;
 61         for(int i=head[sta];~i;i=next[i])
 62             if(len[i]&&dis[to[i]]>dis[sta]+pr[i])
 63             {
 64                 dis[to[i]]=dis[sta]+pr[i];
 65                 pre[to[i]]=i;
 66                 if(!vis[to[i]]) vis[to[i]]=true,q[t++]=to[i];
 67             }
 68     }
 69     return pre[T]!=-1;
 70 }
 71 
 72 inline void updata()
 73 {
 74     for(int i=pre[T];~i;i=pre[to[i^1]])
 75     {
 76         len[i]-=1; len[i^1]+=1;
 77     }
 78 }
 79 
 80 inline void go()
 81 {
 82     int ans=0,num;
 83     for(int i=1;i<=p;i++)
 84     {
 85         num=0;
 86         build(i);
 87         while(spfa()) ans+=dis[T],updata(),num++;
 88         if(num!=sumc) {puts("-1");return;}
 89     }
 90     printf("%d\n",ans);
 91 } 
 92 
 93 int main()
 94 {
 95     while(scanf("%d%d%d",&n,&m,&p))
 96     {
 97         if(n==0&&m==0&&p==0) break;
 98         read(); go();
 99     }
100     return 0;
101 } 
没有人能阻止我前进的步伐,除了我自己!
原文地址:https://www.cnblogs.com/proverbs/p/2852025.html