题意

$n$个点从左向右依次排列,有$m$条双向道路

问从起点到终点,再从终点回到起点,在经过的点不同的情况下最多能经过几个点

Sol

首先,问题可以转化为求两条互不相交的路径,使得点数最多

为了满足流量的限制,肯定会想到拆点,把每个点拆为两个,连流量为$1$,费用为$1$的边

起点和终点连费用为1,流量为2的边

输出方案比较蛋疼,我是dfs两次,然后第二次倒着输出

但是$a->c->a$这种情况会WA,so只好打表喽

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<queue>
  5. #include<map>
  6. #include<iostream>
  7. using namespace std;
  8. const int MAXN = 1e4 + , INF = 1e9 + ;
  9. inline int read() {
  10. char c = getchar(); int x = , f = ;
  11. while(c < '' || c > '') {if(c == '-') f = ; c = getchar();}
  12. while(c >= '' && c <= '') x = x * + c - '', c = getchar();
  13. return x * f;
  14. }
  15. int N, M, S, T;
  16. map<string, int> ID;
  17. map<int, string> nam;
  18. int flag[MAXN];
  19. struct Edge {
  20. int u, v, w, f, nxt, vi;
  21. }E[MAXN];
  22. int head[MAXN], num = ;
  23. inline void add_edge(int x, int y, int w, int f) {
  24. E[num] = (Edge) {x, y, -w, f, head[x], };
  25. head[x] = num++;
  26. }
  27. inline void AddEdge(int x, int y, int w, int f) {
  28. add_edge(x, y, w, f); add_edge(y, x, -w, );
  29. }
  30. int dis[MAXN], vis[MAXN], Pre[MAXN];
  31. bool SPFA() {
  32. memset(dis, 0x3f, sizeof(dis));
  33. memset(vis, , sizeof(vis));
  34. queue<int> q; q.push(S); dis[S] = ;
  35. while(!q.empty()) {
  36. int p = q.front(); q.pop(); vis[p] = ;
  37. for(int i = head[p]; i != -; i = E[i].nxt) {
  38. int to = E[i].v;
  39. if(E[i].f && dis[to] > dis[p] + E[i].w) {
  40. dis[to] = dis[p] + E[i].w; Pre[to] = i;
  41. if(!vis[to]) vis[to] = , q.push(to);
  42. }
  43. }
  44. }
  45. return dis[T] <= INF;
  46. }
  47. int F() {
  48. int flow = INF;
  49. for(int i = T; i != S; i = E[Pre[i]].u) flow = min(flow, E[Pre[i]].f);
  50. for(int i = T; i != S; i = E[Pre[i]].u) E[Pre[i]].f -= flow, E[Pre[i] ^ ].f += flow;
  51. return flow * dis[T];
  52. }
  53. int MCMF() {
  54. int ans = ;
  55. while(SPFA()) ans += F();
  56. return ans;
  57. }
  58. int out[][MAXN], tot[];
  59. void dfs(int now, int opt) {
  60. if(vis[now] || now == N) return ;
  61. vis[now] = ;
  62. for(int i = head[now]; i != -; i = E[i].nxt) {
  63. int to = E[i].v;
  64. if((E[i].u <= N && E[i].v >= N && (E[i].u + N != to)) || (to > N && to - N < out[opt][tot[opt]])) continue;
  65. if(!vis[to] && E[i].f < ) {
  66. E[i].vi = ;
  67. if(to == E[i].u + N) out[opt][++tot[opt]] = E[i].u;
  68. dfs(E[i].v, opt);
  69. }
  70. }
  71. }
  72. int main() {
  73. memset(head, -, sizeof(head));
  74. N = read(); M = read(); S = ; T = N + N;
  75. for(int i = ; i <= N; i++) {
  76. string s; cin >> s; ID[s] = i; nam[i] = s;
  77. AddEdge(i, i + N, , (i == || i == N) ? : );
  78. }
  79. for(int i = ; i <= M; i++) {
  80. string a, b; cin >> a >> b;
  81. if(ID[a] > ID[b]) swap(a, b);
  82. AddEdge(ID[a] + N, ID[b], , );
  83. }
  84. int ans = -MCMF() - ;
  85. if(ans <= -) {puts("No Solution!"); return ;}
  86. if(ans == ) {
  87. printf("2\n");
  88. cout << nam[] << endl;
  89. cout << nam[N] << endl;
  90. cout << nam[] << endl;
  91. return ;
  92. }
  93. printf("%d\n", ans);
  94. memset(vis, , sizeof(vis)); dfs(, );
  95. memset(vis, , sizeof(vis));
  96. for(int i = ; i <= tot[]; i++) vis[out[][i]] = ; vis[] = ;
  97. dfs(, );
  98. for(int i = ; i <= tot[]; i++)
  99. cout << nam[out[][i]] << endl;
  100. cout << nam[N] << endl;
  101. for(int i = tot[]; i >= ; i--)
  102. cout << nam[out[][i]] << endl;
  103. return ;
  104. }
  105. /*
  106.  
  107. */

洛谷P2770 航空路线问题(费用流)的更多相关文章

  1. 洛谷P2770 航空路线问题(费用流)

    传送门 完了这题好厉害……字符串什么的好麻烦…… 要求从$1$到$n$的路径,不重复,经过边数最多 每一个点拆成两个,$A_i,B_i$,然后$A_i$到$B_i$连容量为$1$,费用为$1$的边,保 ...

  2. 洛谷 P2770 航空路线问题【最大费用最大流】

    记得cnt=1!!因为是无向图所以可以把回来的路看成另一条向东的路.字符串用map处理即可.拆点限制流量,除了1和n是(i,i+n,2)表示可以经过两次,其他点都拆成(i,i+n,1),费用设为1,原 ...

  3. 洛谷P2770 航空路线问题 最小费用流

    Code: #include<cstdio> #include<iostream> #include<algorithm> #include<vector&g ...

  4. 洛谷 1004 dp或最大费用流

    思路: dp方法: 设dp[i][j][k][l]为两条没有交叉的路径分别走到(i,j)和(k,l)处最大价值. 则转移方程为 dp[i][j][k][l]=max(dp[i-1][j][k-1][l ...

  5. 洛谷P4003 无限之环(费用流)

    传送门 神仙题啊……不看题解我可能一年都不一定做得出来……FlashHu大佬太强啦 到底是得有怎样的脑回路才能一眼看去就是费用流啊…… 建好图之后套个板子就好了,那么我们着重来讨论一下怎么建图 首先, ...

  6. 洛谷P4012 深海机器人问题(费用流)

    题目描述 深海资源考察探险队的潜艇将到达深海的海底进行科学考察. 潜艇内有多个深海机器人.潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动. 深海机器人在移动中还必须沿途采集海底生物标本.沿途生 ...

  7. 洛谷P2517 HAOI2010 订货 (费用流)

    标准的费用流问题,关键在于巧妙地建模 一共有n个月份,源点设为0,汇点设为n+1 1.源点向所有月份连边,容量为正无穷,费用为该月进货的费用 2.每个月向下一个月连边,容量为仓库容量,费用为存货费用 ...

  8. 洛谷P4016 负载平衡问题 费用流

    这道题还是很好的. 考察了选手对网络流的理解. 首先,任意两个相邻点之间的运货量时没有限制的. 我们可以将相邻点之间的流量建为无限大,单位费用设为 1,代表运输一个货物需耗费一个代价. 由于题目要求最 ...

  9. 洛谷.1251.餐巾计划问题(费用流SPFA)

    题目链接 /* 每一天的餐巾需求相当于必须遍历某些点若干次 设q[i]为Dayi需求量 (x,y)表示边x容y费 将每个点i拆成i,i',由i'->T连(q[i],0)的边,表示求最大流的话一定 ...

随机推荐

  1. YTU 2417: C语言习题 字符串长度

    2417: C语言习题 字符串长度 时间限制: 1 Sec  内存限制: 128 MB 提交: 758  解决: 548 题目描述 写一函数,求一个字符串的长度.在main函数中输入字符串,并输出其长 ...

  2. maven安装的详细步骤

    1.下载maven的bin,在apache官方网站下载.window系统下的下载红色方框的 2.解压后, 把bin的位置设在环境变量里,新建环境变量 MAVEN_HOME.这个配置是方便以后更换mav ...

  3. LA-4726 (斜率优化+单调队列)

    题意: 给定一个01序列,选一个长度至少为L 的连续子序列使其平均值最大;输出这个子序列的起点和终点;如果有多个答案,输出长度最小的,还有多个就输出第一个编号最小的; 思路: 用sum[i]表示[1, ...

  4. iOS设备闪光灯控制

    很多时候都需要在APP中控制闪光灯的开关状态,譬如扫描二维码.控制iOS设备的闪光灯代码非常简单,短短几行代码就可以搞定: AVCaptureDevice *device = [AVCaptureDe ...

  5. Python的单元测试工具——doctest

    doctest是一个python标准库自带的轻量单元测试工具,适合实现一些简单的单元测试.它可以在docstring中寻找测试用例并执行,比较输出结果与期望值是否符合. 基本用法使用doctest需要 ...

  6. 国产免费的visio替代品edraw mind map,用来话流程图够用了

    最新版Edraw Mind Map可以创建基本的思维导图.气泡图和基本流程图,提供了强大的设计功能,包括丰富设计素材.全面的页面布局定义.预置的符号库与绘图工具等.创建的图形,可以导出为常用图像格式. ...

  7. 看鸟哥的Linux私房菜的一些命令自我总结(一)

    -显示目前所支持的语言  echo &LANG -修改语言成为英文系统  LANG=en_US -显示日历的命令 cal [[month] year] -惯用关机命令 shutdown 参数: ...

  8. (链接)Tomcat设置Session的失效方式

    tomcat 设置session过期时间(四种方式):https://blog.csdn.net/liuxiao723846/article/details/50055075 tomcat里设置ses ...

  9. Cg(C for Graphic)语言语义词与语义绑定详述 (转)

    摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人” 语义词( Semantic )与语义绑定 ...

  10. PHP数组直接相加和array_merge的区别

    array_merge是很常用的数组合并函数,但是两个数组直接相加对开发也是很有帮助的,两者之间有什么差别,这里记录一下: 首先是以数字为索引 array_merge会将两个数组按照先后顺序组成一个新 ...