2017 icpc 青島站 K. Our Journey of Xian Ends 最小費用流
阿新 • • 發佈:2018-11-22
題意:這英文題真是比六級閱讀還難讀,給你一個無向圖,求西安-->上海-->青島-->上海的最短路,每個城市有一個機場,但是上海有兩個機場 虹橋機場和浦東機場,上海這兩個機場可以互達(你可以從西安到浦東,然後再從虹橋到青島,距離為0),每個機場只能下飛機和上飛機一次,且最後必須要到達上海的浦東以及過程中不能從浦東出發去任何地方。
思路:由於是無向圖,肯定要將每個點拆成入點和出點,普通城市入點到出點費用為0,流量為1,我們發現,上海的虹橋必須要走兩次,青島也是走兩次(進一次,出一次),西安和浦東只能走一次(進一次),上海-->青島 肯定是虹橋到青島,我們可以理解為,從青島和西安兩條路線走向虹橋,然後青島再走一條路線到浦東,求總距離最小,思路清晰了,起點到西安流量為1,到青島,流量為2,虹橋到終點,流量為2,浦東到終點,流量為1,這些點的入點到出點的流量也是一樣,然後完成建圖就ac。
#include<cstdio> #include<cstring> #include<map> #include<vector> #include<string> #include<queue> #include<algorithm> using namespace std; const int maxn=20005,inf=1e8; map<string,int>mp; struct Edge { int from,to,cap,flow,cost; Edge(int a,int b,int c,int d,int e) { from=a,to=b,cap=c,flow=d,cost=e; } }; struct MCMF{ int n,m,s,t; vector<Edge>edges; vector<int>G[maxn]; int inq[maxn]; int d[maxn]; int p[maxn]; int a[maxn]; void init(int n) { this->n=n; for(int i=0;i<=n;i++)G[i].clear(); edges.clear(); } void add(int from,int to,int cap,int cost) { edges.push_back(Edge(from,to,cap,0,cost)); edges.push_back(Edge(to,from,0,0,-cost)); m=edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool bellman(int s,int t,int& flow,int& cost) { for(int i=0;i<=n;i++)d[i]=inf,inq[i]=0; d[s]=0;inq[s]=1;p[s]=0;a[s]=inf; queue<int>Q; Q.push(s); while(!Q.empty()) { int u=Q.front();Q.pop(); inq[u]=0; for(int i=0;i<G[u].size();i++) { Edge& e=edges[G[u][i]]; if(e.cap>e.flow&&d[e.to]>d[u]+e.cost) { d[e.to]=d[u]+e.cost; p[e.to]=G[u][i]; a[e.to]=min(a[u],e.cap-e.flow); if(!inq[e.to]) { Q.push(e.to); inq[e.to]=1; } } } } if(d[t]==inf)return false; flow+=a[t]; cost+=d[t]*a[t]; int u=t; while(u!=s) { edges[p[u]].flow+=a[t]; edges[p[u]^1].flow-=a[t]; u=edges[p[u]].from; } return true; } int mincost(int s,int t) { int flow=0,cost=0; while(bellman(s,t,flow,cost)); if(flow!=3)return -1; return cost; } }solve; char s1[4][10]={"Xian","Qingdao","Hongqiao","Pudong"}; struct node { char s[15],t[15]; int w; }a[maxn]; int main() { int T; scanf("%d",&T); while(T--) { mp.clear(); for(int i=0;i<4;i++)mp[s1[i]]=i+1; int n=4,m,w; scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%s%s%d",a[i].s,a[i].t,&a[i].w); if(!mp[a[i].s])mp[a[i].s]=++n; if(!mp[a[i].t])mp[a[i].t]=++n; } int tot=n; n+=n; for(int i=1;i<=m;i++) { int u=mp[a[i].s]; int v=mp[a[i].t]; solve.add(u+tot,v,3,a[i].w); solve.add(v+tot,u,3,a[i].w); } int s=++n; int t=++n; solve.add(s,1,1,0);solve.add(1,1+tot,1,0); solve.add(s,2,2,0);solve.add(2,2+tot,2,0); solve.add(3+tot,t,2,0);solve.add(3,3+tot,2,0); solve.add(4+tot,t,1,0);solve.add(4,4+tot,1,0); for(int i=5;i<=tot;i++)solve.add(i,i+tot,1,0); solve.n=n; printf("%d\n",solve.mincost(s,t)); solve.init(n); } }