【网络流24题之航空线路】(只求方案数)xoj1248
来源:互联网 发布:js如何获取select的值 编辑:程序博客网 时间:2024/05/22 13:39
题目描述
给定一张航空图,图中顶点代表城市,边代表2城市间的直通航线。现要求找出一条满 足下述限制条件的且途经城市最多的旅行路线。
(1)从最西端城市出发,单向从西向东途经若干城市到达最东端城市,然后再单向从东 向西飞回起点(可途经若干城市)。
(2)除起点城市外,任何城市只能访问1次。
对于给定的航空图,试设计一个算法找出一条满足要求的最佳航空旅行路线。
输入
由文件input.txt提供输入数据。文件第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.txt 中。
文件第1 行是旅行路 线中所访问的城市总数M。
// 接下来的M+1 行是旅行路线的城市名,每行写1 个城市名。
// 首先是出发城市名,然后按访问顺序列出其它城市名。
//注意,最后1行(终点城市)的城市名 必然是出发城市名。
如果问题无解,则输出“No Solution!”。
样例输入
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
样例输出
7
题解
- 根据题意,首先我们要找出题目的限制。就是每个城市做多只能经过一次(起点可以经过两次,我们把终点也看成可以经过两次)。可以用容量为1(两次为2)的边来限制,题目又要求经过最多城市,我们可以求一个最大费用流(插入费用时变负数,按照最小费用的过程来做,答案再取反)。建模比较容易,只需要将每个点拆成两个点,一个代表进入城市,一个代表离开城市,显然,城市之间的边容量可以为inf,花费为0(已经有S->i和i->T的边限制)。
具体代码:
#include <iostream>#include <cstdio>#include <queue>#include <cstring>#include <map>#define _(d) while(d (((ch=getchar())>47)&&ch<58))using namespace std;const int MaxN=223,Maxe=MaxN*MaxN/2;const int inf=0x7fffffff;int N,V,ans,h[MaxN],pre[MaxN],vst[MaxN],d[MaxN];int S,T,tt,from[Maxe],to[Maxe],flow[Maxe],cst[Maxe],nxt[Maxe];string str[MaxN];map<string,int> hash;inline void Get(int &x){char ch;_(!);x=ch-48;_()x=(x<<3)+(x<<1)+ch-48;}inline void addedge(int u,int v,int w,int cc){ from[tt]=u;to[tt]=v;flow[tt]=w;cst[tt]=cc; nxt[tt]=h[u];h[u]=tt++; }inline void add(int u,int v,int w,int cc){ addedge(u,v,w,cc);addedge(v,u,0,-cc); }queue<int> q;bool spfa(){ for(int i=0;i<MaxN;i++) pre[i]=-1,vst[i]=0,d[i]=inf; q.push(S);vst[S]=1;d[S]=0; while(!q.empty()) { int u=q.front();q.pop(); vst[u]=0; for(int i=h[u];i!=-1;i=nxt[i]) { int v=to[i]; if(flow[i]&&d[v]>d[u]+cst[i]) { d[v]=d[u]+cst[i]; pre[v]=i; if(!vst[v]) { q.push(v); vst[v]=1; } } } } return d[T]!=inf;}inline void work(){ int ft; while(spfa()) { ft=inf; for(int i=T;i!=S;i=from[pre[i]]){ft=min(ft,flow[pre[i]]);} for(int i=T;i!=S;i=from[pre[i]]) { int k=pre[i]; flow[k]-=ft; flow[k^1]+=ft; ans+=cst[k]*ft; } } return;}int main(){ for(int i=0;i<MaxN;i++) h[i]=-1; string str1,str2; Get(N);Get(V); S=1;T=2*N; add(S,S+N,2,-1);add(N,T,2,-1); for(int i=1;i<=N;i++) { cin>>str[i]; hash[str[i]]=i; if(i>1&&i<N) add(i,i+N,1,-1); } for(int i=1;i<=V;i++) { cin>>str1>>str2; int a=hash[str1],b=hash[str2]; if(a>b) swap(a,b); add(a+N,b,inf,0); } work(); if(flow[0]) printf("No Solution!\n"); else printf("%d\n",-2-ans); return 0; }
- 【网络流24题之航空线路】(只求方案数)xoj1248
- 航空路线问题[网络流24题之11]
- 网络流24题之T11 航空路线问题
- 【网络流24题】航空路线问题
- [网络流24题]航空路线问题
- 网络流二十四题之十一 —— 航空路线问题(AIRL)
- 线性规划与网络流24题 11航空路线问题
- 网络流与线性规划24题11航空路线问题
- [网络流24题 #11]航空路线问题
- 【线性规划与网络流24题 11】航空路线
- 网络流24题11. 航空路线问题
- 「网络流 24 题」航空路线问题
- 【网络流24题】航空路线问题(最大费用流)
- loj6122「网络流 24 题」航空路线问题(最长不相交路径)
- ExpressRoute 线路的虚拟网络数
- 线性规划与网络流24——航空路线问题
- 网络流24题之飞行员配对方案问题
- 网络流24题之飞行员配对方案问题
- 解决出现android.os.NetworkOnMainThreadException异常
- 每天进步一点点——使用SQL提示
- Android数据库的批处理操作
- 利用environment文件实现heat资源注册
- 星云测试-给你的Android应用做个深度体检
- 【网络流24题之航空线路】(只求方案数)xoj1248
- ireport detail换行问题
- grid edit 属性
- 黑马程序员-[OC语言] 第七篇:foundation框架之NSArray、NSDitctionary 基本用法
- OOzie调度sqoop1 Action 从mysql导入数据到hive
- 实现Dota技能冷却效果
- STL:使用模板计算一组整形数的最小值
- KMeans聚类算法思想与可视化
- jquery选择器大全