洛谷 P4015 運輸問題(最小費用最大流)
阿新 • • 發佈:2018-12-11
輸入輸出樣例
輸入樣例#1:
2 3
220 280
170 120 210
77 39 105
150 186 122
輸出樣例#1:
48500
69140
題意:中文題不說了
思路:注意,要求所有的貨物都要運送到商店,用最小費用最大流,保證在最大流的前提下,得到最小的費用。
源點到倉庫,流量為倉庫容量,費用0;商店到匯點,流量為商店容量,費用0;倉庫到商店,流量inf,費用c。跑最大流的時候,能夠保證所有的貨物都到達商店,套模板,得到最小費用,然後把c取負數,再跑一次得到最大費用
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> #include<queue> using namespace std; const int maxn=1000; const int maxm=100000; const int INF=0x3f3f3f3f; struct Edge { int to,next,cap,cost; Edge(){} Edge(int to,int next,int cap,int cost):to(to),next(next),cap(cap),cost(cost){} }edge[maxm]; int first[maxn],tot; int pre[maxn],dis[maxn]; bool vis[maxn]; int N; //節點總個數,節點編號從0~N-1 void init(int n){ N=n; tot=0; memset(first,-1,sizeof(first)); } void addedge(int u,int v,int cap,int cost){ edge[tot]=Edge(v,first[u],cap,cost); first[u]=tot++; edge[tot]=Edge(u,first[v],0,-cost); first[v]=tot++; } bool spfa(int s,int t){ queue<int>q; for(int i=0;i<N;i++) { dis[i]=INF; vis[i]=false; pre[i]=-1; } dis[s]=0; vis[s]=true; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=false; for(int i= first[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(edge[i].cap&&dis[v]>dis[u]+edge[i].cost ){ dis[v]=dis[u]+edge[i].cost; pre[v]=i; if(!vis[v]) { vis[v]=true; q.push(v); } } } } if(pre[t]==-1) return false; else return true; } int minCostMaxflow(int s,int t,int &cost) { int flow=0; cost = 0; while(spfa(s,t)) { int Min=INF; for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){ if(Min >edge[i].cap)Min=edge[i].cap; } for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){ edge[i].cap-=Min; edge[i^1].cap+=Min; cost+=edge[i].cost*Min; } flow+=Min; } return flow; } int main(){ init(500);//初始化!!!!!!!!!! int m,n; scanf("%d%d",&m,&n); int a[110]; int b[110]; int c[110][110]; for(int i=1;i<=m;i++)scanf("%d",&a[i]); for(int i=1;i<=n;i++)scanf("%d",&b[i]); for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ scanf("%d",&c[i][j]); } } for(int i=1;i<=m;i++)addedge(0,i,a[i],0); for(int i=1;i<=n;i++)addedge(i+100,201,b[i],0); for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ addedge(i,j+100,INF,c[i][j]); } } int sp=0; int tp=201; int cost; minCostMaxflow(sp,tp,cost); printf("%d\n",cost); init(500); for(int i=1;i<=m;i++)addedge(0,i,a[i],0); for(int i=1;i<=n;i++)addedge(i+100,201,b[i],0); for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ addedge(i,j+100,INF,-c[i][j]); } } minCostMaxflow(sp,tp,cost); printf("%d\n",-cost); return 0; }