网络流二十四题之十一 —— 航空路线问题(AIRL)
2016-05-17 21:01
435 查看
航空路线问题
Description
给定一张航空图,图中顶点代表城市,边代表 2 城市间的直通航线。现要求找出一条满足下述限制条件的且途经城市最多的旅行路线。
(1) 从最西端城市出发,单向从西向东途经若干城市到达最东端城市,然后再单向从东
向西飞回起点(可途经若干城市)。
(2) 除起点城市外,任何城市只能访问 1 次。
对于给定的航空图,试设计一个算法找出一条满足要求的最佳航空旅行路线。
Input
第 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
第 1 行是旅行路线中所访问的城市总数 M。接下来的 M+1 行是旅行路线的城市名,每行写 1 个城市名。
首先是出发城市名,然后按访问顺序列出其它城市名。
注意,最后 1 行(终点城市)的城市名必然是出发城市名。
如果问题无解,则输出“No Solution!”。
Sample Input
8 9Vancouver
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
7Vancouver
Edmonton
Montreal
Halifax
Toronto
Winnipeg
Calgary
Vancouver
Solution
这是一道简单的费用流的题目。一开始做这道题,我竟然没有发现必须要从西到东!
弄得我最开始求费用流时费了很大功夫。
步入正题。
首先,一去 —— 一回,我们完全可以看成最东方的那座城市有两条路径到最西方的城市!
将每个城市拆点,保证每个城市只经过一次。
然后将最西方的城市连上汇点,将最东方的城市连上源点。
将每一条航线的容量设为 1,费用也设为 1。
然后求最大费用最大流即可。
注意:如果最西方的城市与最东方的城市直接连上了,那么这条边的容量应该为 2(因为这条边可以看作一去一回的两条路径)。
Code
[cpp] #include <iostream>#include <cstdio>
#include <cstring>
#include <assert.h>
#include <queue>
#define MAXV 1000010
#define MAXE 100010
#define INF 0x3f3f3f3f
#define Min(x,y) ((x)<(y)?(x):(y))
#define ss 0
#define tt 100005
using namespace std;
int n,m,ans,weight,tot;
char s[110][50];
char s1[50],s2[50];
int from[MAXV],cnt,nxt[MAXV],wei[MAXV];
int head[MAXE],dis[MAXE],data[MAXV],flow[MAXV];
int pre[MAXE];
bool in_stack[MAXE];
queue<int>q;
int come[4][500],come2[4][500];
inline int in(){
int x=0;
char c=getchar();
while(c<‘0’||c>‘9’)c=getchar();
while(c>=‘0’&&c<=‘9’){x=x*10+c-‘0’;c=getchar();}
return x;
}
void add(int x,int y,int a,int b){
from[cnt]=x;nxt[cnt]=head[x];data[cnt]=y;wei[cnt]=b;flow[cnt]=a;head[x]=cnt++;
from[cnt]=y;nxt[cnt]=head[y];data[cnt]=x;wei[cnt]=-b;flow[cnt]=0;head[y]=cnt++;
}
bool BFS(){
memset(dis,0xc0,sizeof dis);
q.push(ss);dis[ss]=0;in_stack[ss]=true;
pre[ss]=pre[tt]=-1;
while(!q.empty()){
int now=q.front();
q.pop();
in_stack[now]=false;
for(int i=head[now];i!=-1;i=nxt[i]){
if(flow[i]&&wei[i]+dis[now]>dis[data[i]]){
dis[data[i]]=wei[i]+dis[now];
pre[data[i]]=(i^1);
// if(data[i]==tt)break;
if(!in_stack[data[i]]){q.push(data[i]);in_stack[data[i]]=true;}
}
}
}
return pre[tt]>0;
}
void dfs(){
tot++;
int Low=INF,tmp;
for(int i=pre[tt];i!=-1;i=pre[data[i]])Low=Min(Low,flow[i^1]);
for(int i=pre[tt];i!=-1;i=pre[data[i]]){
flow[i^1]-=Low;
flow[i]+=Low;
come[tot][++come[tot][0]]=data[i];
}
tmp=come[tot][0]+1;
for(int i=pre[tt];i!=-1;i=pre[data[i]])come2[tot][–tmp]=data[i]-n;
weight+=Low;
ans+=(dis[tt])*Low;
}
int main(){
memset(head,-1,sizeof head);
n=in();m=in();
for(int i=1;i<=n;i++){
scanf(”%s”,s[i]);
if(i==1||i==n)add(i+n,i,2,0);
else add(i+n,i,1,0);
}
add(ss,n+n,2,0);
add(1,tt,2,0);
for(int i=1;i<=m;i++){
scanf(”%s%s”,s1,s2);
int pos1,pos2;
for(pos1=1;pos1<=n;pos1++)if(0==strcmp(s[pos1],s1))break;
for(pos2=1;pos2<=n;pos2++)if(0==strcmp(s[pos2],s2))break;
if(pos1==1&&pos2==n)add(pos2,pos1+n,2,1);
else if(pos1==n&&pos2==1)add(pos1,pos2+n,2,1);
else{
if(pos1>pos2)add(pos1,pos2+n,1,1);
else add(pos2,pos1+n,1,1);
}
}
while(BFS())dfs();
if(weight<2){
printf(”No Solution!\n”);
return 0;
}
else printf(“%d\n”,ans);
for(int i=1;i<=come[1][0];i++)if(come[1][i]!=ss&&come[1][i]!=tt&&come[1][i]>=1&&come[1][i]<=n)printf(“%s\n”,s[come[1][i]]);
// printf(“%d\n”,come[2][0]);
for(int i=3;i<=come[2][0];i++)if(come2[2][i]!=ss&&come2[2][i]!=tt&&come2[2][i]>=1&&come2[2][i]<=n)printf(“%s\n”,s[come2[2][i]]);
if(tot==1)for(int i=3;i<=come[1][0];i++)if(come2[1][i]!=ss&&come2[1][i]!=tt&&come2[1][i]>=1&&come2[1][i]<=n)printf(“%s\n”,s[come2[1][i]]);
return 0;
}
相关文章推荐
- 运输层的TCP协议
- BZOJ1001 狼抓兔子(裸网络流)
- Tcpdump抓取 Android 网络包
- TCP的连接建立与连接释放
- 网络 协议与分层结构 的学习心得
- Socket编程------模拟QQ聊天(TCP)
- 网络编程之FIFO
- https 常见问题一 PKIX path building failed
- TCP协议的建立与释放及TCP的有限状态基
- 关于Android6.0API,找不到org.apache.http.Header问题记录。
- Okhttp session持久化
- Android HttpConnection获取图片太大 处理办法 防止OOM
- UNIX网络编程之管道
- httpclient 访问https
- Okhttp session持久化
- HttpClient 教程 (一)
- 自己动手从网络加载,缓存,压缩图片
- Android 网络请求框架android-async-http简单使用
- nodejs:本地文件夹http服务器http-server
- http状态码301与302的区别