题目链接 \(Click\) \(Here\)

本来想调剂心情没想到写了那么久,还被\(dreagonm\)神仙嘲讽不会传纸条,我真是太弱了\(QAQ\)(原因:最开始写最大费用最大流一直想消圈,最后发现自己完全是\(zz\)了)

这个题是最大费用最大流,避免正环的关键在于只从西向东连边。还有要注意题目中并没有说能任一点开始结束,所以必须是两条\(1->n\)的路线。

路径输出方法真的是学到了,看下面代码吧。还有注意只有\(1->n\)一条边的特判。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N = 400010;
  4. const int M = 4000010;
  5. const int INF = 0x3f3f3f3f;
  6. int cnt = -1, head[N];
  7. struct edge {
  8. int nxt, to, f, w;
  9. }e[M];
  10. void add_edge (int from, int to, int flw, int val) {
  11. e[++cnt].nxt = head[from];
  12. e[cnt].to = to;
  13. e[cnt].f = flw;
  14. e[cnt].w = val;
  15. head[from] = cnt;
  16. }
  17. void add_len (int u, int v, int f, int w) {
  18. add_edge (u, v, f, +w);
  19. add_edge (v, u, 0, -w);
  20. }
  21. int n, m;
  22. map <string, int> mp;
  23. string s1, s2, str[110];
  24. int inn (int x) {return n * 0 + x;}
  25. int out (int x) {return n * 1 + x;}
  26. queue <int> q;
  27. int vis[N], dis[N], flow[N];
  28. int pre_edge[N], pre_node[N], max_flow, max_cost;
  29. bool spfa (int s, int t) {
  30. memset (vis, 0, sizeof (vis));
  31. memset (dis, -0x3f, sizeof (dis));
  32. memset (flow, 0x3f, sizeof (flow));
  33. dis[s] = 0; vis[s] = true; q.push (s);
  34. while (!q.empty ()) {
  35. int u = q.front (); q.pop ();
  36. for (int i = head[u]; ~i; i = e[i].nxt) {
  37. int v = e[i].to;
  38. if (dis[v] < dis[u] + e[i].w && e[i].f) {
  39. dis[v] = dis[u] + e[i].w;
  40. flow[v] = min (flow[u], e[i].f);
  41. pre_edge[v] = i;
  42. pre_node[v] = u;
  43. if (!vis[v]) {
  44. vis[v] = true;
  45. q.push (v);
  46. }
  47. }
  48. }
  49. vis[u] = false;
  50. }
  51. return dis[t] != dis[0];
  52. }
  53. void dfs1 (int x) {
  54. cout << str[x - n] << endl;//第一遍dfs正序输出
  55. vis[x] = 1;//不让第二次dfs再找到这个点
  56. for (int i = head[x]; ~i; i = e[i].nxt) {
  57. if (e[i].to <= n && !e[i].f) {
  58. dfs1 (e[i].to + n);
  59. break;
  60. }//第一次dfs只找一条路径,找到就break
  61. }
  62. }
  63. void dfs2 (int x) {
  64. vis[x - n] = 1;
  65. for (int i = head[x]; ~i; i = e[i].nxt) {
  66. if (e[i].to <= n && !e[i].f && !vis[e[i].to + n]) {
  67. dfs2 (e[i].to + n);
  68. }//不走第一次路径走过的点
  69. }
  70. cout << str[x - n] << endl;//第二次dfs倒序输出
  71. }//vis[n]在第一次dfs已经设为1,不会输出第二次
  72. int main () {
  73. memset (head, -1, sizeof (head));
  74. cin >> n >> m;
  75. int s = n * 2 + 1;
  76. int t = n * 2 + 2;
  77. for (int i = 1; i <= n; ++i) {
  78. cin >> str[i]; mp[str[i]] = i;
  79. add_len (inn (i), out (i), 1, 1);
  80. }
  81. add_len (inn (1), out (1), 1, 0);
  82. add_len (inn (n), out (n), 1, 0);
  83. add_len (s, inn (1), 2, 0);
  84. add_len (out (n), t, 2, 0);
  85. bool have = false;
  86. for (int i = 1; i <= m; ++i) {
  87. cin >> s1 >> s2;
  88. if (mp[s1] > mp[s2]) swap (s1, s2);
  89. have |= (mp[s1] == 1 && mp[s2] == n);
  90. add_len (out (mp[s1]), inn (mp[s2]), 1, 0);
  91. }
  92. max_flow = 0, max_cost = 0;
  93. while (spfa (s, t)) {
  94. max_flow += flow[t];
  95. max_cost += dis[t] * flow[t];
  96. int u = t;
  97. while (u != s) {
  98. e[pre_edge[u] ^ 0].f -= flow[t];
  99. e[pre_edge[u] ^ 1].f += flow[t];
  100. u = pre_node[u];
  101. }
  102. }
  103. if (max_flow == 1 && have) {
  104. cout << max_cost << endl;
  105. cout << str[1] << endl << str[n] << endl << str[1] << endl;
  106. } else if (max_flow == 2){
  107. memset (vis, 0, sizeof (vis));
  108. cout << max_cost << endl;
  109. dfs1 (n + 1); dfs2 (n + 1);
  110. } else puts ("No Solution!");
  111. }

Luogu P2770 航空路线问题的更多相关文章

  1. 网络流 P2770 航空路线问题

    #include <cstdio> #include <cstdlib> #include <map> #include <queue> #includ ...

  2. P2770 航空路线问题

    \(\color{#0066ff}{题目描述}\) 给定一张航空图,图中顶点代表城市,边代表 2 城市间的直通航线.现要求找出一条满足下述限制条件的且途经城市最多的旅行路线. (1)从最西端城市出发, ...

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

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

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

    题意 $n$个点从左向右依次排列,有$m$条双向道路 问从起点到终点,再从终点回到起点,在经过的点不同的情况下最多能经过几个点 Sol 首先,问题可以转化为求两条互不相交的路径,使得点数最多 为了满足 ...

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

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

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

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

  7. 【题解】【网络流24题】航空路线问题 [P2770] [Loj6122]

    [题解][网络流24题]航空路线问题 [P2770] [Loj6122] 传送门:航空路线问题 \([P2770]\) \([Loj6122]\) [题目描述] 给出一张有向图,每个点(除了起点 \( ...

  8. JS前端三维地球渲染——中国各城市航空路线展示

    前言 我还从来没有写过有关纯JS的文章(上次的矢量瓦片展示除外,相对较简单.),自己也学习过JS.CSS等前端知识,了解JQuery.React等框架,但是自己艺术天分实在不过关,不太喜欢前端设计,比 ...

  9. loj #6122. 「网络流 24 题」航空路线问题

    #6122. 「网络流 24 题」航空路线问题 题目描述 给定一张航空图,图中顶点代表城市,边代表两个城市间的直通航线.现要求找出一条满足下述限制条件的且途经城市最多的旅行路线. 从最西端城市出发,单 ...

随机推荐

  1. Mybatis之collection嵌套查询mapper文件写法

    mapper.xml写法举例 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper ...

  2. Bootstrap之表格、表单应用

    代码: <!DOCTYPE html> <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml&q ...

  3. SQL 给视图赋权限

    授予表权限 创建视图 授予视图权限 测试权限 复杂程度: 初级 数据要求: 使用自备的数据 您可以使用 SQL 在企业级地理数据库中创建表和要素类的视图. 本主题中的示例显示如何使用 Microsof ...

  4. css 媒体查询 注意点

    1, 媒体查询表达式之间还可以用逗号,@media (max-width:800px), print  它表示或的意思 @media (max-width: 800px) OR print; 2, n ...

  5. 【C/C++】龙格库塔+亚当姆斯求解数值微分初值问题

    /* 解数值微分初值问题: 龙格-库塔法求前k个初值 + 亚当姆斯法 */ #include<bits/stdc++.h> using namespace std; double f(do ...

  6. vs + babelua + cocos2d-x

    https://blog.csdn.net/dugaoda/article/details/60467037 https://blog.csdn.net/taotanty/article/detail ...

  7. Python中第三方模块requests解析

    一.简述 Requests HTTP Library 二.模块框架 ''' __version__ _internal_utils adapters api auth certs compat coo ...

  8. 如何让自己定义的memory使用fpga自带的memory资源

    前言 本文解决方法来源: http://quartushelp.altera.com/13.1/mergedProjects/hdl/vlog/vlog_file_dir_ram.htm 如果你自己V ...

  9. pytorch搭建简单网络

    pytorch搭建一个简单神经网络 import torch import torch.nn as nn # 定义数据 # x:输入数据 # y:标签 x = torch.Tensor([[0.2, ...

  10. Linux服务器定时健康检查,发生故障自动微信告警

    此脚本适用于于各种Linux环境,可以实现各种监控项目,可自定义阀值,实现不同监控效果已在原有脚本基础上做了简化,提取了主要功能目前实现的有:1.磁盘监控2.内存监控3.cpu负荷监控4.进程数监控5 ...