洛谷P2770 航空路线问题(费用流)
题意
$n$个点从左向右依次排列,有$m$条双向道路
问从起点到终点,再从终点回到起点,在经过的点不同的情况下最多能经过几个点
Sol
首先,问题可以转化为求两条互不相交的路径,使得点数最多
为了满足流量的限制,肯定会想到拆点,把每个点拆为两个,连流量为$1$,费用为$1$的边
起点和终点连费用为1,流量为2的边
输出方案比较蛋疼,我是dfs两次,然后第二次倒着输出
但是$a->c->a$这种情况会WA,so只好打表喽
- #include<cstdio>
- #include<algorithm>
- #include<cstring>
- #include<queue>
- #include<map>
- #include<iostream>
- using namespace std;
- const int MAXN = 1e4 + , INF = 1e9 + ;
- inline int read() {
- char c = getchar(); int x = , f = ;
- while(c < '' || c > '') {if(c == '-') f = ; c = getchar();}
- while(c >= '' && c <= '') x = x * + c - '', c = getchar();
- return x * f;
- }
- int N, M, S, T;
- map<string, int> ID;
- map<int, string> nam;
- int flag[MAXN];
- struct Edge {
- int u, v, w, f, nxt, vi;
- }E[MAXN];
- int head[MAXN], num = ;
- inline void add_edge(int x, int y, int w, int f) {
- E[num] = (Edge) {x, y, -w, f, head[x], };
- head[x] = num++;
- }
- inline void AddEdge(int x, int y, int w, int f) {
- add_edge(x, y, w, f); add_edge(y, x, -w, );
- }
- int dis[MAXN], vis[MAXN], Pre[MAXN];
- bool SPFA() {
- memset(dis, 0x3f, sizeof(dis));
- memset(vis, , sizeof(vis));
- queue<int> q; q.push(S); dis[S] = ;
- while(!q.empty()) {
- int p = q.front(); q.pop(); vis[p] = ;
- for(int i = head[p]; i != -; i = E[i].nxt) {
- int to = E[i].v;
- if(E[i].f && dis[to] > dis[p] + E[i].w) {
- dis[to] = dis[p] + E[i].w; Pre[to] = i;
- if(!vis[to]) vis[to] = , q.push(to);
- }
- }
- }
- return dis[T] <= INF;
- }
- int F() {
- int flow = INF;
- for(int i = T; i != S; i = E[Pre[i]].u) flow = min(flow, E[Pre[i]].f);
- for(int i = T; i != S; i = E[Pre[i]].u) E[Pre[i]].f -= flow, E[Pre[i] ^ ].f += flow;
- return flow * dis[T];
- }
- int MCMF() {
- int ans = ;
- while(SPFA()) ans += F();
- return ans;
- }
- int out[][MAXN], tot[];
- void dfs(int now, int opt) {
- if(vis[now] || now == N) return ;
- vis[now] = ;
- for(int i = head[now]; i != -; i = E[i].nxt) {
- int to = E[i].v;
- if((E[i].u <= N && E[i].v >= N && (E[i].u + N != to)) || (to > N && to - N < out[opt][tot[opt]])) continue;
- if(!vis[to] && E[i].f < ) {
- E[i].vi = ;
- if(to == E[i].u + N) out[opt][++tot[opt]] = E[i].u;
- dfs(E[i].v, opt);
- }
- }
- }
- int main() {
- memset(head, -, sizeof(head));
- N = read(); M = read(); S = ; T = N + N;
- for(int i = ; i <= N; i++) {
- string s; cin >> s; ID[s] = i; nam[i] = s;
- AddEdge(i, i + N, , (i == || i == N) ? : );
- }
- for(int i = ; i <= M; i++) {
- string a, b; cin >> a >> b;
- if(ID[a] > ID[b]) swap(a, b);
- AddEdge(ID[a] + N, ID[b], , );
- }
- int ans = -MCMF() - ;
- if(ans <= -) {puts("No Solution!"); return ;}
- if(ans == ) {
- printf("2\n");
- cout << nam[] << endl;
- cout << nam[N] << endl;
- cout << nam[] << endl;
- return ;
- }
- printf("%d\n", ans);
- memset(vis, , sizeof(vis)); dfs(, );
- memset(vis, , sizeof(vis));
- for(int i = ; i <= tot[]; i++) vis[out[][i]] = ; vis[] = ;
- dfs(, );
- for(int i = ; i <= tot[]; i++)
- cout << nam[out[][i]] << endl;
- cout << nam[N] << endl;
- for(int i = tot[]; i >= ; i--)
- cout << nam[out[][i]] << endl;
- return ;
- }
- /*
- */
洛谷P2770 航空路线问题(费用流)的更多相关文章
- 洛谷P2770 航空路线问题(费用流)
传送门 完了这题好厉害……字符串什么的好麻烦…… 要求从$1$到$n$的路径,不重复,经过边数最多 每一个点拆成两个,$A_i,B_i$,然后$A_i$到$B_i$连容量为$1$,费用为$1$的边,保 ...
- 洛谷 P2770 航空路线问题【最大费用最大流】
记得cnt=1!!因为是无向图所以可以把回来的路看成另一条向东的路.字符串用map处理即可.拆点限制流量,除了1和n是(i,i+n,2)表示可以经过两次,其他点都拆成(i,i+n,1),费用设为1,原 ...
- 洛谷P2770 航空路线问题 最小费用流
Code: #include<cstdio> #include<iostream> #include<algorithm> #include<vector&g ...
- 洛谷 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 ...
- 洛谷P4003 无限之环(费用流)
传送门 神仙题啊……不看题解我可能一年都不一定做得出来……FlashHu大佬太强啦 到底是得有怎样的脑回路才能一眼看去就是费用流啊…… 建好图之后套个板子就好了,那么我们着重来讨论一下怎么建图 首先, ...
- 洛谷P4012 深海机器人问题(费用流)
题目描述 深海资源考察探险队的潜艇将到达深海的海底进行科学考察. 潜艇内有多个深海机器人.潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动. 深海机器人在移动中还必须沿途采集海底生物标本.沿途生 ...
- 洛谷P2517 HAOI2010 订货 (费用流)
标准的费用流问题,关键在于巧妙地建模 一共有n个月份,源点设为0,汇点设为n+1 1.源点向所有月份连边,容量为正无穷,费用为该月进货的费用 2.每个月向下一个月连边,容量为仓库容量,费用为存货费用 ...
- 洛谷P4016 负载平衡问题 费用流
这道题还是很好的. 考察了选手对网络流的理解. 首先,任意两个相邻点之间的运货量时没有限制的. 我们可以将相邻点之间的流量建为无限大,单位费用设为 1,代表运输一个货物需耗费一个代价. 由于题目要求最 ...
- 洛谷.1251.餐巾计划问题(费用流SPFA)
题目链接 /* 每一天的餐巾需求相当于必须遍历某些点若干次 设q[i]为Dayi需求量 (x,y)表示边x容y费 将每个点i拆成i,i',由i'->T连(q[i],0)的边,表示求最大流的话一定 ...
随机推荐
- YTU 2417: C语言习题 字符串长度
2417: C语言习题 字符串长度 时间限制: 1 Sec 内存限制: 128 MB 提交: 758 解决: 548 题目描述 写一函数,求一个字符串的长度.在main函数中输入字符串,并输出其长 ...
- maven安装的详细步骤
1.下载maven的bin,在apache官方网站下载.window系统下的下载红色方框的 2.解压后, 把bin的位置设在环境变量里,新建环境变量 MAVEN_HOME.这个配置是方便以后更换mav ...
- LA-4726 (斜率优化+单调队列)
题意: 给定一个01序列,选一个长度至少为L 的连续子序列使其平均值最大;输出这个子序列的起点和终点;如果有多个答案,输出长度最小的,还有多个就输出第一个编号最小的; 思路: 用sum[i]表示[1, ...
- iOS设备闪光灯控制
很多时候都需要在APP中控制闪光灯的开关状态,譬如扫描二维码.控制iOS设备的闪光灯代码非常简单,短短几行代码就可以搞定: AVCaptureDevice *device = [AVCaptureDe ...
- Python的单元测试工具——doctest
doctest是一个python标准库自带的轻量单元测试工具,适合实现一些简单的单元测试.它可以在docstring中寻找测试用例并执行,比较输出结果与期望值是否符合. 基本用法使用doctest需要 ...
- 国产免费的visio替代品edraw mind map,用来话流程图够用了
最新版Edraw Mind Map可以创建基本的思维导图.气泡图和基本流程图,提供了强大的设计功能,包括丰富设计素材.全面的页面布局定义.预置的符号库与绘图工具等.创建的图形,可以导出为常用图像格式. ...
- 看鸟哥的Linux私房菜的一些命令自我总结(一)
-显示目前所支持的语言 echo &LANG -修改语言成为英文系统 LANG=en_US -显示日历的命令 cal [[month] year] -惯用关机命令 shutdown 参数: ...
- (链接)Tomcat设置Session的失效方式
tomcat 设置session过期时间(四种方式):https://blog.csdn.net/liuxiao723846/article/details/50055075 tomcat里设置ses ...
- Cg(C for Graphic)语言语义词与语义绑定详述 (转)
摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人” 语义词( Semantic )与语义绑定 ...
- PHP数组直接相加和array_merge的区别
array_merge是很常用的数组合并函数,但是两个数组直接相加对开发也是很有帮助的,两者之间有什么差别,这里记录一下: 首先是以数字为索引 array_merge会将两个数组按照先后顺序组成一个新 ...