[题解] [网络流二十四题(十一)] 航空路线问题(最大费用最大流)
2017-12-28 17:04
507 查看
11.航空路线问题
题目描述 Description给定一张航空图,图中顶点代表城市,边代表2城市间的直通航线。现要求找出一条满足下述限制条件的且途经城市最多的旅行路线
(1)从最西端城市出发,单向从西向东途经若干城市到达最东端城市,然后再单向从东向西飞回起点(可途经若干城市)
(2)除起点城市外,任何城市只能访问1次
输入描述 Input Description
第1行有2个正整数N和V,N表示城市数,N<100,V表示直飞航线数。接下来的N行中每一行是一个城市名,可乘飞机访问这些城市。城市名出现的顺序是从西向东。也就是说,设i,j是城市表列中城市出现的顺序,当i>j时,表示城市i在城市j的东边,而且不会有2个城市在同一条经线上。城市名是一个长度不超过15的字符串,串中的字符可以是字母或阿拉伯数字。例如,AGR34或BEL4。再接下来的V行中,每行有2个城市名,中间用空格隔开,如 city1 city2 表示city1到city2 有一条直通航线,从city2到city1也有一条直通航线。
输出描述 Output Description
将最佳航空旅行路线输出,第1行是旅行路线中所访问的城市总数M。接下来的M+1行是旅行路线的城市名,每行写1个城市名。首先是出发城市名,然后按访问顺序列出其它城市名。注意,最后1行(终点城市)的城市名必然是出发城市名。如果问题无解,则输出”No Solution!”
样例输入 Sample Input
8 9
Vancouver
Yellowknife
Edmonton
Calgary
Winnipeg
Toronto
Montreal
Halifax
Vancouver Edmonton
Vancouver Calgary
Calgary Winnipeg
Winnipeg Toronto
Toronto Halifax
Montreal Halifax
Edmonton Montreal
Edmonton Yellowknife
Edmonton Calgary
样例输出 Sample Output
7
Vancouver
Edmonton
Montreal
Halifax
Toronto
Winnipeg
Calgary
Vancover
分析: 从西飞向东,再从东边飞回起点,就相当于两条航线从最西边出发到达最东端,所以我们直接将s与最西端的地点相连,将最东端的点与t相连。怎么保证每个点除起点外只经过一次呢,我们将每个地点拆成Xi和Yi,连一条容量为1的边。因为我们流法的特殊性,最西端的点与最东端的点都需要将其连一条容量为2的边。再来考虑怎么让流经的城市最多:将两个城市之间的航线设置花费为1,求最大费用最大流即可
建图: 将每个点拆成Xi和Yi,最西端和最东端的点Xi和Yi之间连一条容量为2的边,其他点Xi和Yi之间连一条容量为1的边。s向Xwest连一条容量为INF的边,Yeast向t连一条容量为INF的边。从西至东若两个城市联通,则从西边城市向东边城市连一条容量为1,花费为1的边
若流量为2,则输出最大费用,若流量为1,则说明只有从最西端直接飞向最东端一种方案,所以输出2,若流量为0,输出”No Solution!”
#include <bits/stdc++.h> using namespace std; #define INF 2100000000 map <string,int> m; queue <int> q; string a,b,x[500]; struct node { int to; int flow; int cost; int next; }e[50000]; int n,v,s,t,tot=1; bool pd[500]; int head[500]; int pre[500]; int dis[500]; int pe[500]; int ans[500]; bool Q; int read() { int ans=0,flag=1; char ch=getchar(); while( (ch>'9' || ch<'0') && ch!='-' ) ch=getchar(); if(ch=='-') flag=-1,ch=getchar(); while(ch>='0' && ch<='9') ans=ans*10+ch-'0',ch=getchar(); return ans*flag; } void addedge(int u,int v,int flow,int cost) { e[++tot].to=v; e[tot].flow=flow; e[tot].cost=cost; e[tot].next=head[u]; head[u]=tot; e[++tot].to=u; e[tot].flow=0; e[tot].cost=-cost; e[tot].next=head[v]; head[v]=tot; return ; } bool spfa() { memset(pre,-1,sizeof(pre)); memset(dis,-1,sizeof(dis)); dis[s]=0; pd[s]=1; while(!q.empty()) q.pop(); q.push(s); while(!q.empty()) { int now=q.front(); q.pop(); pd[now]=0; for(int i=head[now];i;i=e[i].next) { if(dis[e[i].to]<dis[now]+e[i].cost && e[i].flow>0) { dis[e[i].to]=dis[now]+e[i].cost; pre[e[i].to]=now; pe[e[i].to]=i; if(!pd[e[i].to]) { q.push(e[i].to); pd[e[i].to]=1; } } } } return pre[t]!=-1; } void search() { memset(pd,0,sizeof(pd)); int now=1; cout<<endl<<x[now]; now+=n; do{ for(int i=head[now];i;i=e[i].next) { if(e[i].to!=s && e[i].to!=t && e[i^1].flow!=0 && !pd[e[i].to]) { now=e[i].to; cout<<endl<<x[now]; pd[now]=1; now+=n; break; } } }while(now!=n+n); now=1+n; pd =0; ans[++ans[0]]=1; do{ for(int i=head[now];i;i=e[i].next) { if(e[i].to!=s && e[i].to!=t && e[i^1].flow!=0 && !pd[e[i].to]) { now=e[i].to; ans[++ans[0]]=now; pd[now]=1; now+=n; break; } } }while(now!=n+n); for(int i=ans[0]-1;i>=1;i--) cout<<endl<<x[ans[i]]; return ; } void Mincost() { int cost=0; int flow=0; while(spfa()) { int f=INF; for(int i=t;i!=s;i=pre[i]) f=min(f,e[pe[i]].flow); flow+=f; for(int i=t;i!=s;i=pre[i]) { cost+=f*e[pe[i]].cost; e[pe[i]].flow-=f; e[pe[i]^1].flow+=f; } } if(flow==2) { printf("%d",cost); search(); } else if(Q) { printf("2"); cout<<endl<<x[1]; cout<<endl<<x ; cout<<endl<<x[1]; } else printf("No Solution!"); return ; } int main() { n=read(),v=read(); s=0;t=n*2+1; for(int i=1;i<=n;i++) cin>>x[i],m[x[i]]=i; for(int i=1;i<=v;i++) { cin>>a>>b; if((m[a]==1 && m[b]==n) || (m[a]==n && m[b]==1)) Q=1; addedge(m[a]+n,m[b],1,1); } for(int i=1;i<=n;i++) if(i==1 || i==n) addedge(i,i+n,2,0); else addedge(i,i+n,1,0); addedge(s,1,INF,0); addedge(n+n,t,INF,0); Mincost(); return 0; }
相关文章推荐
- 网络流二十四题之十一 —— 航空路线问题(AIRL)
- 【网络流24题】No.11(航空路线问题 最长不相交路径 最大费用流)
- 【网络流24题】航空路线问题(最大费用流)
- 网络流24题(11)航空路线问题(最大费用最大流)
- [题解] [网络流二十四题(五)] 圆桌问题(最大流)
- 洛谷 P2770 航空路线问题【最大费用最大流】
- 洛谷P2770:航空路线问题【最大费用最大流】
- LOJ6122 「网络流 24 题 - 18」 航空路线问题 最长不相交路径 坠大费用坠大流
- [题解] [网络流二十四题(三)] 最小路径覆盖问题(二分图最大匹配)
- 【网络流二十四题 太空飞行计划问题】【最大权闭合图->最小割】
- [网络流24题]航空路线问题
- 线性规划与网络流24题の18 分配问题(最小费用最大流、最大费用最大流)
- 线性规划与网络流24题 11航空路线问题
- 【网络流二十四题 方格取数问题】【二分图点权最大独立集->最小割】
- 【网络流24题】航空线路问题(费用流)
- 线性规划与网络流24题之分配问题 最大费用最大流、最小费用最大流、二分图的最佳匹配
- [题解] [网络流二十四题(一)] 飞行员配对方案问题 (二分图匹配)
- [题解] [网络流二十四题(九)] 方格取数问题(最小割)
- 「网络流 24 题」航空路线问题
- luogu4015: 运输问题(网络流/最小费用最大流/最大费用最大流)