多源多汇费用流——poj2516
网络流的题好难。。感觉有点遭不住了
这题用矩阵存图,然后把k个物品,每个物品都求一次费用流
/* 多源多汇的费用流 其实是k个费用流 */ #include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define maxn 205 struct Edge{int to,nxt,w,c;}e[maxn<<2]; int head[maxn],tot,n,m,s,t; void init(){} void add(int u,int v,int w,int c){} int sum_need[maxn],sum_offer[maxn]; int offer[maxn][maxn],need[maxn][maxn],mp[maxn][maxn],cost[maxn][maxn],K,sum,pre[maxn]; int dis[maxn],vis[maxn]; int spfa(){ queue<int>q; for(int i=0;i<=t;i++){vis[i]=false;dis[i]=inf;} vis[s]=1;dis[s]=0;q.push(s); while(!q.empty()){ int k=q.front();q.pop();vis[k]=false; for(int i=0;i<=t;i++) if(mp[k][i] && dis[i]>dis[k]+cost[k][i]){ dis[i]=dis[k]+cost[k][i]; pre[i]=k; if(!vis[i]){ vis[i]=1; q.push(i); } } } if(dis[t]!=inf)return 1; return 0; } int fond(){ int Min=inf,res=0; while(spfa()){ for(int i=t;i!=s;i=pre[i]) Min=min(Min,mp[pre[i]][i]); for(int i=t;i!=s;i=pre[i]){ mp[pre[i]][i]-=Min; mp[i][pre[i]]+=Min; res+=cost[pre[i]][i]*Min; } } return res; } int main(){ while(cin>>n>>m>>K,n&&m&&K){ sum=0; memset(sum_need,0,sizeof sum_need); memset(sum_offer,0,sizeof sum_offer); for(int i=1;i<=n;i++) for(int j=1;j<=K;j++){ scanf("%d",&need[i][j]); sum_need[j]+=need[i][j]; } for(int i=1;i<=m;i++) for(int j=1;j<=K;j++){ scanf("%d",&offer[i][j]); sum_offer[j]+=offer[i][j]; } int sign=0; for(int i=1;i<=K;i++) if(sum_offer[i]<sum_need[i]){ sign=1; break; } s=0; t=n+m+1; for(int k=1;k<=K;k++){ memset(mp,0,sizeof mp); memset(cost,0,sizeof cost); //第k件物品 供应商->店主的运费 for(int i=1+m;i<=n+m;i++) for(int j=1;j<=m;j++){ scanf("%d",&cost[j][i]); cost[i][j]-=cost[j][i];//反向边的费用 } if(sign==1)continue; for(int i=1;i<=m;i++)//s->供应商 mp[s][i]=offer[i][k]; for(int i=1;i<=m;i++)//供应商->店主 for(int j=m+1;j<=m+n;j++) mp[i][j]=offer[i][k]; for(int i=m+1;i<=m+n;i++)//店主->t mp[i][t]=need[i-m][k]; sum+=fond(); } if(sign==1) printf("-1\n"); else printf("%d\n",sum); } }