Our Journey of Dalian Ends && Our Journey of Xian Ends 最小费用最大流

2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 Our Journey of Dalian Ends

题意:要求先从大连到上海,再从上海打西安,中途会经过其他城市,每个城市只能去一次,出一次,给出航班信息,问最小花费。

每个城市只能去一次,出一次,那么很明显需要对每个城市拆点,就分成入点和出点,然后如果按照题意说法,把汇点连大连和上海,然后把上海和西安连汇点,那么很明显不对,

因为跑出来的可能是从上海直接到的上海,然后大连到西安,所以不能把跟汇点和源点相连的设在同一点,那么我们就可以汇点跟上海连,大连和西安跟源点连,或者反过来也可以。

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<queue>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<tr1/unordered_map>
 7 using namespace std;
 8 const int N=2e4+11,M=1e6+11,inf=1e9+7;
 9 struct Side{
10     int v,ne,w,val;
11 }S[M<<1];
12 string s1[M],s2[M];
13 tr1::unordered_map<string,int> mmp;
14 int n,sn,sb,se,head[N],ww[N],vis[N],flow[N],lu[N],dis[N];
15 void init(){
16     sn=0;
17     sb=0;se=n*2+1;
18     for(int i=sb;i<=se;i++) head[i]=-1;
19 }
20 void add(int u,int v,int w,int val){
21     S[sn].w=w;S[sn].val=val;
22     S[sn].v=v;S[sn].ne=head[u];
23     head[u]=sn++;
24 }
25 void addE(int u,int v,int w,int val){
26     add(u,v,w,val);add(v,u,0,-val); 
27 }
28 bool spfa(){
29     queue<int> q;
30     for(int i=sb;i<=se;i++){
31         dis[i]=inf;
32         vis[i]=0;
33         flow[i]=inf;
34         lu[i]=-1;
35     }
36     dis[sb]=0;
37     vis[sb]=1;
38     q.push(sb);
39     int u,v;
40     while(!q.empty()){
41         u=q.front();q.pop();vis[u]=0;
42         for(int i=head[u];~i;i=S[i].ne){
43             v=S[i].v;
44             if(S[i].w>0&&dis[v]>dis[u]+S[i].val){
45                 lu[v]=i;
46                 dis[v]=dis[u]+S[i].val;
47                 flow[v]=min(flow[u],S[i].w);
48                 if(!vis[v]){
49                     vis[v]=1;
50                     q.push(v);
51                 }
52             }
53         }
54     }
55     return dis[se]!=inf; 
56 }
57 int mfml(){
58     int ans=0,ansc=0;
59     while(spfa()){
60         ans+=flow[se];
61         ansc+=flow[se]*dis[se];
62         for(int i=lu[se];~i;i=lu[S[i^1].v]){
63             S[i].w-=flow[se];
64             S[i^1].w+=flow[se];
65         }
66     }
67     if(ans==2) return ansc;
68     return -1;
69 }
70 int main(){
71     int t,m;
72     scanf("%d",&t);
73     while(t--){
74         scanf("%d",&m);
75         n=0;mmp.clear();
76         for(int i=0;i<m;i++){
77             cin>>s1[i]>>s2[i]>>ww[i];
78             if(!mmp.count(s1[i])) mmp[s1[i]]=++n;
79             if(!mmp.count(s2[i])) mmp[s2[i]]=++n;
80         }
81         init();
82         for(int i=1;i<=n;i++) addE(i,i+n,1,0);
83         addE(mmp["Shanghai"],mmp["Shanghai"]+n,1,0);
84         addE(sb,mmp["Xian"],1,0);
85         addE(sb,mmp["Dalian"],1,0);
86         addE(mmp["Shanghai"]+n,se,2,0);
87         for(int i=0;i<m;i++){
88             addE(mmp[s1[i]]+n,mmp[s2[i]],1,ww[i]);
89             addE(mmp[s2[i]]+n,mmp[s1[i]],1,ww[i]);
90         }
91         printf("%d
",mfml());
92     }
93     return 0;
94 } 
旅游哦

 ACM-ICPC 2017 Asia QingdaoOur Journey of Xian Ends

题意:跟上面类似,不过就是变成了,上海分成了两个之间有高速路的机场,虹桥跟浦东,然后这个高速路不计入那个进出里面。

明白题意之后,可以知道路线就西安到虹桥到青岛到浦东还有西安到浦东到虹桥到青岛到虹桥到浦东,这两条。

而不管是第一条还是第二条,如果只算航班信息的话,我们都可以统一出一个建图方法,源点连虹桥,流量为2,源点连浦东,流量为1,西安连汇点,流量为1,青岛连汇点流量为2,还有要注意青岛跟虹桥间的流量应该为2,应该它可以直接通过这个航班做一个轮回。

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<queue>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<tr1/unordered_map>
  7 using namespace std;
  8 const int N=2e4+11,M=1e6+11,inf=1e9+7;
  9 struct Side{
 10     int v,ne,w,val;
 11 }S[M<<1];
 12 string s1[M],s2[M];
 13 tr1::unordered_map<string,int> mmp;
 14 int n,sn,sb,se,head[N],ww[N],vis[N],flow[N],lu[N],dis[N];
 15 void init(){
 16     sn=0;
 17     sb=0;se=n*2+1;
 18     for(int i=sb;i<=se;i++) head[i]=-1;
 19 }
 20 void add(int u,int v,int w,int val){
 21     S[sn].w=w;S[sn].val=val;
 22     S[sn].v=v;S[sn].ne=head[u];
 23     head[u]=sn++;
 24 }
 25 void addE(int u,int v,int w,int val){
 26     add(u,v,w,val);add(v,u,0,-val); 
 27 }
 28 bool spfa(){
 29     queue<int> q;
 30     for(int i=sb;i<=se;i++){
 31         dis[i]=inf;
 32         vis[i]=0;
 33         flow[i]=inf;
 34         lu[i]=-1;
 35     }
 36     dis[sb]=0;
 37     vis[sb]=1;
 38     q.push(sb);
 39     int u,v;
 40     while(!q.empty()){
 41         u=q.front();q.pop();vis[u]=0;
 42         for(int i=head[u];~i;i=S[i].ne){
 43             v=S[i].v;
 44             if(S[i].w>0&&dis[v]>dis[u]+S[i].val){
 45                 lu[v]=i;
 46                 dis[v]=dis[u]+S[i].val;
 47                 flow[v]=min(flow[u],S[i].w);
 48                 if(!vis[v]){
 49                     vis[v]=1;
 50                     q.push(v);
 51                 }
 52             }
 53         }
 54     }
 55     return dis[se]!=inf; 
 56 }
 57 int mfml(){
 58     int ans=0,ansc=0;
 59     while(spfa()){
 60         ans+=flow[se];
 61         ansc+=flow[se]*dis[se];
 62         for(int i=lu[se];~i;i=lu[S[i^1].v]){
 63             S[i].w-=flow[se];
 64             S[i^1].w+=flow[se];
 65         }
 66     }
 67     if(ans==3) return ansc;
 68     return -1;
 69 }
 70 int main(){
 71     int t,m;
 72     scanf("%d",&t);
 73     while(t--){
 74         scanf("%d",&m);
 75         n=0;mmp.clear();
 76         for(int i=0;i<m;i++){
 77             cin>>s1[i]>>s2[i]>>ww[i];
 78             if(!mmp.count(s1[i])) mmp[s1[i]]=++n;
 79             if(!mmp.count(s2[i])) mmp[s2[i]]=++n;
 80         }
 81         init();
 82         for(int i=1;i<=n;i++) addE(i,i+n,1,0);
 83         addE(mmp["Hongqiao"],mmp["Hongqiao"]+n,1,0);
 84         addE(mmp["Qingdao"],mmp["Qingdao"]+n,1,0);
 85         addE(sb,mmp["Pudong"],1,0);
 86         addE(sb,mmp["Hongqiao"],2,0);
 87         addE(mmp["Xian"]+n,se,1,0);
 88         addE(mmp["Qingdao"]+n,se,2,0);
 89         for(int i=0,w;i<m;i++){
 90             if(s1[i]=="Qingdao"&&s2[i]=="Hongqiao") w=2;
 91             else if(s2[i]=="Qingdao"&&s1[i]=="Hongqiao") w=2;
 92             else w=1;
 93             addE(mmp[s1[i]]+n,mmp[s2[i]],w,ww[i]);
 94             addE(mmp[s2[i]]+n,mmp[s1[i]],w,ww[i]);
 95             
 96         }
 97         printf("%d
",mfml());
 98     }
 99     return 0;
100 }
公费哦
原文地址:https://www.cnblogs.com/LMCC1108/p/11734630.html