[luoguP2770] 航空路线问题(最小费用最大流)
模型
求最长两条不相交路径,用最大费用最大流解决。
实现
为了限制经过次数,将每个点i拆成xi,yi.
1、从xi向yi连一条容量为1,费用为1的有向边(1<i<N),
2、从x1向y1连一条容量为2,费用为1的有向边,
3、从xN向yN连一条容量为2,费用为1的有向边,
4、如果存在边(i,j)(i<j)从yi向xj连一条容量为1,费用为0的有向边.
如果存在边(i,j)(i>j),那么交换i,j,再连边,因为原题是过去再回来,我们要转换成网络流的图,只求起点到终点的最大费用流。
如果存在边(i,j)(i==1 && j==n) 那么要连一条容量为2,费用为0的边。
因为原题要求最大费用流,所以我们需要将费用取反,求出费用后再取反回来。
求x1到yN的最大费用最大流.若(x1,y1)满流,则有解,答案为最大费用最大流-2;否则,无解.
分析
每条航线都是自西向东,本题可以转化为求航线图中从1到N两条不相交的路径,使得路径长度之和最大。转化为网络流模型,就是找两条最长的增广路。由于每个城市只能访问一次,要把城市
拆成两个点,之间连接一条容量为1的边,费用设为1。因为要找两条路径,所以起始点和终点内部的边容量要设为2。那么费用流值-2就是两条路径长度之和,为什么减2,因为有两条容量为2
的边多算了1的费用。求最大费用最大流后,如果(<1.a>,<1.b>)不是满流,那么我们找到的路径不够2条(可能是1条,也可能0条),所以无解。
——代码
#include <map>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 10001
#define M 1000001
#define min(x, y) ((x) < (y) ? (x) : (y)) int n, m, cnt, flow, ans, s, t;
std::string str[], s1, s2;
std::map <std::string, int> p;
int head[N], to[M], val[M], cost[M], next[M], dis[N], pre[N];
bool vis[N]; inline void add(int x, int y, int z, int c)
{
to[cnt] = y;
val[cnt] = z;
cost[cnt] = c;
next[cnt] = head[x];
head[x] = cnt++;
} inline bool spfa()
{
int i, u, v;
std::queue <int> q;
memset(vis, , sizeof(vis));
memset(pre, -, sizeof(pre));
memset(dis, / , sizeof(dis));
q.push(s);
dis[s] = ;
while(!q.empty())
{
u = q.front(), q.pop();
vis[u] = ;
for(i = head[u]; i ^ -; i = next[i])
{
v = to[i];
if(val[i] && dis[v] > dis[u] + cost[i])
{
dis[v] = dis[u] + cost[i];
pre[v] = i;
if(!vis[v])
{
q.push(v);
vis[v] = ;
}
}
}
}
return pre[t] ^ -;
} int main()
{
int i, j, d, now;
scanf("%d %d", &n, &m);
s = , t = n << ;
memset(head, -, sizeof(head));
for(i = ; i <= n; i++)
{
std::cin >> str[i];
p[str[i]] = i;
if(i ^ && i ^ n)
add(i, i + n, , -), add(i + n, i, , );
else
add(i, i + n, , -), add(i + n, i, , );
}
for(i = ; i <= m; i++)
{
std::cin >> s1 >> s2;
if(p[s1] > p[s2]) std::swap(s1, s2);
if(p[s1] == && p[s2] == n)
add(p[s1] + n, p[s2], , ), add(p[s2], p[s1] + n, , );
else
add(p[s1] + n, p[s2], , ), add(p[s2], p[s1] + n, , );
}
while(spfa())
{
d = 1e9;
for(i = pre[t]; i ^ -; i = pre[to[i ^ ]]) d = min(d, val[i]);
for(i = pre[t]; i ^ -; i = pre[to[i ^ ]])
{
val[i] -= d;
val[i ^ ] += d;
}
flow += d;
ans += dis[t] * d;
}
if(flow ^ )
{
printf("No Solution!");
return ;
}
printf("%d\n", -ans - );
memset(vis, , sizeof(vis));
vis[] = vis[] = ;
std::cout << str[] << std::endl;
for(i = head[s + n]; i ^ -; i = next[i])
if(!val[i] && !vis[to[i]])
{
now = to[i];
while(!vis[now])
{
vis[now] = ;
std::cout << str[now] << std::endl;
for(j = head[now + n]; j ^ -; j = next[j])
if(!val[j] && !vis[to[j]])
{
now = to[j];
break;
}
}
break;
}
for(i = head[n]; i ^ -; i = next[i])
if(!val[i ^ ] && !vis[to[i] - n])
{
now = to[i] - n;
while(!vis[now])
{
vis[now] = ;
std::cout << str[now] << std::endl;
for(j = head[now]; j ^ -; j = next[j])
if(!val[j ^ ] && !vis[to[j] - n])
{
now = to[j] - n;
break;
}
}
break;
}
std::cout << str[] << std::endl;
return ;
}
[luoguP2770] 航空路线问题(最小费用最大流)的更多相关文章
- bzoj 1877 [SDOI2009]晨跑(最小费用最大流)
Description Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑.仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑. 现在给出一张学校附近的地图,这张地图中包含N个十 ...
- [BZOJ2055]80人环游世界 有上下界最小费用最大流
2055: 80人环游世界 Time Limit: 10 Sec Memory Limit: 64 MB Description 想必大家都看过成龙大哥的<80天环游世界>,里面 ...
- BZOJ 1877:[SDOI2009]晨跑(最小费用最大流)
晨跑DescriptionElaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑.仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑. 现在给出一张学校附近的地图,这张地图中包含N个 ...
- BZOJ 2055 80人环游世界 有上下界最小费用可行流
题意: 现在有这么一个m人的团伙,也想来一次环游世界. 他们打算兵分多路,游遍每一个国家. 因为他们主要分布在东方,所以他们只朝西方进军.设从东方到西方的每一个国家的编号依次为1...N.假若第 ...
- [SDOI2009]晨跑[最小费用最大流]
[SDOI2009]晨跑 最小费用最大流的板子题吧 令 \(i'=i+n\) \(i -> i'\) 建一条流量为1费用为0的边这样就不会对答案有贡献 其次是对 \(m\) 条边建 \(u'-& ...
- [板子]最小费用最大流(Dijkstra增广)
最小费用最大流板子,没有压行.利用重标号让边权非负,用Dijkstra进行增广,在理论和实际上都比SPFA增广快得多.教程略去.转载请随意. #include <cstdio> #incl ...
- bzoj1927最小费用最大流
其实本来打算做最小费用最大流的题目前先来点模板题的,,,结果看到这道题二话不说(之前打太多了)敲了一个dinic,快写完了发现不对 我当时就这表情→ =_=你TM逗我 刚要删突然感觉dinic的模 ...
- ACM/ICPC 之 卡卡的矩阵旅行-最小费用最大流(可做模板)(POJ3422)
将每个点拆分成原点A与伪点B,A->B有两条单向路(邻接表实现时需要建立一条反向的空边,并保证环路费用和为0),一条残留容量为1,费用为本身的负值(便于计算最短路),另一条残留容量+∞,费用为0 ...
- HDU5900 QSC and Master(区间DP + 最小费用最大流)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5900 Description Every school has some legends, ...
- P3381 【模板】最小费用最大流
P3381 [模板]最小费用最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行 ...
随机推荐
- UVA225 Golygons 黄金图形(dfs+回溯)
剪枝1:在同一个维度上的点具有相同的奇偶性,如果奇数数量只有奇数个那么一定不能返回原点. 剪枝2:当前位置怎么也走不回去. 3:沿途判断障碍即可. 在oj上提交0.347s,最快的0.012s,应该有 ...
- 2018.3.16 Ubuntu 解决中文乱码问题
一.乱码的样子类似: °²Àï¿ü ÒÁ¸ñÀ³Ï£ÑÇ˹,°²Àï¿ü ÒÁ¸ñÀ³Ï£ÑÇ˹ 这种乱码称为Gedit中文乱码 打开部分Windows下的txt文本文件的时候,中文显示为乱码.但 ...
- python之道11
day11作业 请写出下列代码的执行结果: 例一: def func1(): print(**'in func1'**) def func2(): print(**'in func2'**) ret ...
- /^/m|/$/m|\b|\B|$&|$`|$'|变量捕获|()?|(?:pattern)|(?<LABEL>PATTERN)|$+{LABEL}|(|)|\g{LABEL}
#!/usr/bin/perl use strict; use warnings; $_=' $$ oinn &&& ninq kdownc aninp kkkk'; if ( ...
- springboot 修改文件上传大小限制
springboot 1.5.9文件上传大小限制spring:http:multipart:maxFileSize:50MbmaxRequestSize:50Mb springboot 2.0文件上传 ...
- javaweb基础(8)_HttpServletResponse生成验证码
一.HttpServletResponse常见应用——生成验证码 1.1.生成随机图片用作验证码 生成图片主要用到了一个BufferedImage类,
- LINQ结合正则表达式查询文件系统
string startFolder = @"D:\Program Files (x86)\Microsoft Visual Studio 12.0\"; IEnumerable& ...
- 什么是静态代码块?java中如何使用空参构造方法自动生成不同名字的对象,使用非静态的属性和静态属性有什么区别,原因是什么?如何理解static关键字
静态代码块?类加载就执行,最先执行 class demo{ static int num; static{ num=10; num*=3; System.out.println("haha& ...
- linux 下使用 curl 访问带多参数,GET掉参数解决方案
url 为 http://mywebsite.com/index.php?a=1&b=2&c=3 web形式下访问url地址,使用 $_GET是可以获取到所有的参数 curl -s ...
- 【概率dp 高斯消元】bzoj3270: 博物馆
一类成环概率dp的操作模式 Description 有一天Petya和他的朋友Vasya在进行他们众多旅行中的一次旅行,他们决定去参观一座城堡博物馆.这座博物馆有着特别的样式.它包含由m条走廊连接的n ...