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

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

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

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

#include <bits/stdc++.h>
using namespace std; const int N = 400010;
const int M = 4000010;
const int INF = 0x3f3f3f3f; int cnt = -1, head[N]; struct edge {
int nxt, to, f, w;
}e[M]; void add_edge (int from, int to, int flw, int val) {
e[++cnt].nxt = head[from];
e[cnt].to = to;
e[cnt].f = flw;
e[cnt].w = val;
head[from] = cnt;
} void add_len (int u, int v, int f, int w) {
add_edge (u, v, f, +w);
add_edge (v, u, 0, -w);
} int n, m; map <string, int> mp; string s1, s2, str[110]; int inn (int x) {return n * 0 + x;}
int out (int x) {return n * 1 + x;} queue <int> q;
int vis[N], dis[N], flow[N];
int pre_edge[N], pre_node[N], max_flow, max_cost; bool spfa (int s, int t) {
memset (vis, 0, sizeof (vis));
memset (dis, -0x3f, sizeof (dis));
memset (flow, 0x3f, sizeof (flow));
dis[s] = 0; vis[s] = true; q.push (s);
while (!q.empty ()) {
int u = q.front (); q.pop ();
for (int i = head[u]; ~i; i = e[i].nxt) {
int v = e[i].to;
if (dis[v] < dis[u] + e[i].w && e[i].f) {
dis[v] = dis[u] + e[i].w;
flow[v] = min (flow[u], e[i].f);
pre_edge[v] = i;
pre_node[v] = u;
if (!vis[v]) {
vis[v] = true;
q.push (v);
}
}
}
vis[u] = false;
}
return dis[t] != dis[0];
} void dfs1 (int x) {
cout << str[x - n] << endl;//第一遍dfs正序输出
vis[x] = 1;//不让第二次dfs再找到这个点
for (int i = head[x]; ~i; i = e[i].nxt) {
if (e[i].to <= n && !e[i].f) {
dfs1 (e[i].to + n);
break;
}//第一次dfs只找一条路径,找到就break
}
} void dfs2 (int x) {
vis[x - n] = 1;
for (int i = head[x]; ~i; i = e[i].nxt) {
if (e[i].to <= n && !e[i].f && !vis[e[i].to + n]) {
dfs2 (e[i].to + n);
}//不走第一次路径走过的点
}
cout << str[x - n] << endl;//第二次dfs倒序输出
}//vis[n]在第一次dfs已经设为1,不会输出第二次 int main () {
memset (head, -1, sizeof (head));
cin >> n >> m;
int s = n * 2 + 1;
int t = n * 2 + 2;
for (int i = 1; i <= n; ++i) {
cin >> str[i]; mp[str[i]] = i;
add_len (inn (i), out (i), 1, 1);
}
add_len (inn (1), out (1), 1, 0);
add_len (inn (n), out (n), 1, 0);
add_len (s, inn (1), 2, 0);
add_len (out (n), t, 2, 0);
bool have = false;
for (int i = 1; i <= m; ++i) {
cin >> s1 >> s2;
if (mp[s1] > mp[s2]) swap (s1, s2);
have |= (mp[s1] == 1 && mp[s2] == n);
add_len (out (mp[s1]), inn (mp[s2]), 1, 0);
}
max_flow = 0, max_cost = 0;
while (spfa (s, t)) {
max_flow += flow[t];
max_cost += dis[t] * flow[t];
int u = t;
while (u != s) {
e[pre_edge[u] ^ 0].f -= flow[t];
e[pre_edge[u] ^ 1].f += flow[t];
u = pre_node[u];
}
}
if (max_flow == 1 && have) {
cout << max_cost << endl;
cout << str[1] << endl << str[n] << endl << str[1] << endl;
} else if (max_flow == 2){
memset (vis, 0, sizeof (vis));
cout << max_cost << endl;
dfs1 (n + 1); dfs2 (n + 1);
} else puts ("No Solution!");
}

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. elasticsearch索引合并

    参考地址:http://cwiki.apachecn.org/display/Elasticsearch/Reindex+API 1.首先插入准备数据,创建两个索引. (1).PUT  http:// ...

  2. Log4j2配置与使用

    依赖包: <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api --> <depend ...

  3. 二、启用Docker支持

    一.使用

  4. LODOP 获取打印设计代码不带INIT初始化语句

    前面的博文生成JS代码模版和文档式模版,生成的是带初始化语句的模版,如果想要打印多个,可以循环多个任务,什么是一个任务,可查看本博客相关博文:Lodop打印语句最基本结构介绍(什么是一个任务)一个任务 ...

  5. 开源 DotNetty 实现的 Modbus TCP/IP 协议

    本项目的目的是为了学习 DotNetty 与 Modbus 协议,参考 modjn 实现功能 0x01: Read Coils (读取线圈/离散量输出状态) 0x02: Read Discrete I ...

  6. 使用update可以防止并发问题(保证数据的准确性),如果使用select会产生并发问题 ; select * from xx for update 给查询开启事务,默认情况下是没有事物的

    update可以锁住数据防止数据被更新且导致与查询出的数据有误差,如果响应条数为0.说明更新失败 则可以回滚事务;

  7. 数据库MySQL5.7.21win64位安装配置

    1,在MySQL官网下载mysql对应版本 https://dev.mysql.com/downloads/mysql/ 2,解压压缩文件到想要的位置 3,配置环境 打开  右键我的电脑-->属 ...

  8. load加载层-layui

    加载样式 //eg1 var index = layer.load(); //eg2 var index = layer.load(1); //换了种风格 //eg3 var index = laye ...

  9. linu系统文件授权命令

  10. K - Transformation HDU - 4578 线段树经典题(好题)

    题意:区间  加   变成定值 乘  区间查询:和 平方和 立方和 思路:超级超级超级麻烦的一道题  设3个Lazy 标记分别为  change 改变mul乘 add加  优先度change>m ...