10806 - Dijkstra, Dijkstra.

//最小费用最大流的问题(它指的是在总流量最大的前提下,总费用最小)

//由于这个题目不用求出总流,所以使用Edmonds-Karp比预流推进更适合

//注意 cost[u][pa[u]]=-cost[pa[u]][u]; 这样就能保证流的再次增广的时候可以"顶"出之前不适合的流

//切不可用两遍dijisktra啊,比如下面数据

6 8 1 2 1 2 3 1 3 6 1 1 4 100 4 5 100 5 6 100 1 3 10 2 6 10

#include <iostream> #include <cstdio> #include <queue> #include <memory.h> using namespace std; const int MAX=105,INF=1<<30; bool inq[MAX]; int m,n,cap[MAX][MAX],flow[MAX][MAX],cost[MAX][MAX], d[MAX],a[MAX],pa[MAX]; queue<int> q; int bfs(){ int f=0,c=0,u,v; memset(flow,0,sizeof(flow)); while(1){ memset(inq,0,sizeof(inq)); for(int i=2;i<=n;i++) d[i]=INF; d[1]=0; inq[1]=true; q.push(1); while(!q.empty()){ u=q.front(); q.pop(); inq[u]=false; for(v=1;v<=n;v++){ if(u==5&&v==2){ /*cout<<endl<<cap[u][v]<<" " <<flow[u][v]<<endl; cout<<d[v]<<" "<<d[u]<<endl; cout<<cost[u][v]<<endl;*/ } if(cap[u][v]>flow[u][v]&&d[v]>d[u]+cost[u][v]){ d[v]=d[u]+cost[u][v]; pa[v]=u; if(!inq[v]){ inq[v]=true; q.push(v); } } } } if(d[n]==INF) break; int a=INF; for(u=n;u!=1;u=pa[u]) a=a<(cap[pa[u]][u]-flow[pa[u]][u])? a:(cap[pa[u]][u]-flow[pa[u]][u]); for(u=n;u!=1;u=pa[u]){ flow[pa[u]][u]+=a; flow[u][pa[u]]-=a; cost[u][pa[u]]=-cost[pa[u]][u]; } //cout<<"a: "<<a<<" d: "<<d[n]<<endl; u=n; /*while(u!=1){ cout<<u<<"<-- ("<<d[pa[u]]<<")"<<" -- "; u=pa[u]; } cout<<1<<endl;*/ c+=d[n]*a; f+=a; if(f==2){ return c; } } return 0; } int main() { freopen("i.txt","r",stdin); int u,v,c,ans; while(cin>>n,n){ cin>>m; memset(cap,0,sizeof(cap)); memset(cost,0,sizeof(cost)); for(int i=0;i<m;i++){ cin>>u>>v>>c; cap[u][v]=cap[v][u]=1; cost[u][v]=cost[v][u]=c; //cap[u][v]=1; //cost[u][v]=c; } ans=bfs(); if(ans) cout<<ans<<endl; else cout<<"Back to jail"<<endl; } return 0; }

你可能感兴趣的:(10806 - Dijkstra, Dijkstra.)