传送门

模型

求最长两条不相交路径,用最大费用最大流解决。

实现

为了限制经过次数,将每个点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] 航空路线问题(最小费用最大流)的更多相关文章

  1. bzoj 1877 [SDOI2009]晨跑(最小费用最大流)

    Description Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑.仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑. 现在给出一张学校附近的地图,这张地图中包含N个十 ...

  2. [BZOJ2055]80人环游世界 有上下界最小费用最大流

    2055: 80人环游世界 Time Limit: 10 Sec  Memory Limit: 64 MB Description     想必大家都看过成龙大哥的<80天环游世界>,里面 ...

  3. BZOJ 1877:[SDOI2009]晨跑(最小费用最大流)

    晨跑DescriptionElaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑.仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑. 现在给出一张学校附近的地图,这张地图中包含N个 ...

  4. BZOJ 2055 80人环游世界 有上下界最小费用可行流

    题意: 现在有这么一个m人的团伙,也想来一次环游世界. 他们打算兵分多路,游遍每一个国家.    因为他们主要分布在东方,所以他们只朝西方进军.设从东方到西方的每一个国家的编号依次为1...N.假若第 ...

  5. [SDOI2009]晨跑[最小费用最大流]

    [SDOI2009]晨跑 最小费用最大流的板子题吧 令 \(i'=i+n\) \(i -> i'\) 建一条流量为1费用为0的边这样就不会对答案有贡献 其次是对 \(m\) 条边建 \(u'-& ...

  6. [板子]最小费用最大流(Dijkstra增广)

    最小费用最大流板子,没有压行.利用重标号让边权非负,用Dijkstra进行增广,在理论和实际上都比SPFA增广快得多.教程略去.转载请随意. #include <cstdio> #incl ...

  7. bzoj1927最小费用最大流

    其实本来打算做最小费用最大流的题目前先来点模板题的,,,结果看到这道题二话不说(之前打太多了)敲了一个dinic,快写完了发现不对 我当时就这表情→   =_=你TM逗我 刚要删突然感觉dinic的模 ...

  8. ACM/ICPC 之 卡卡的矩阵旅行-最小费用最大流(可做模板)(POJ3422)

    将每个点拆分成原点A与伪点B,A->B有两条单向路(邻接表实现时需要建立一条反向的空边,并保证环路费用和为0),一条残留容量为1,费用为本身的负值(便于计算最短路),另一条残留容量+∞,费用为0 ...

  9. HDU5900 QSC and Master(区间DP + 最小费用最大流)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5900 Description Every school has some legends, ...

  10. P3381 【模板】最小费用最大流

    P3381 [模板]最小费用最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行 ...

随机推荐

  1. UVA225 Golygons 黄金图形(dfs+回溯)

    剪枝1:在同一个维度上的点具有相同的奇偶性,如果奇数数量只有奇数个那么一定不能返回原点. 剪枝2:当前位置怎么也走不回去. 3:沿途判断障碍即可. 在oj上提交0.347s,最快的0.012s,应该有 ...

  2. 2018.3.16 Ubuntu 解决中文乱码问题

    一.乱码的样子类似: °²Àï¿ü ÒÁ¸ñÀ³Ï£ÑÇ˹,°²Àï¿ü ÒÁ¸ñÀ³Ï£ÑÇ˹ 这种乱码称为Gedit中文乱码 打开部分Windows下的txt文本文件的时候,中文显示为乱码.但 ...

  3. python之道11

    day11作业 请写出下列代码的执行结果: 例一: def func1(): print(**'in func1'**) def func2(): print(**'in func2'**) ret ...

  4. /^/m|/$/m|\b|\B|$&|$`|$'|变量捕获|()?|(?:pattern)|(?<LABEL>PATTERN)|$+{LABEL}|(|)|\g{LABEL}

    #!/usr/bin/perl use strict; use warnings; $_=' $$ oinn &&& ninq kdownc aninp kkkk'; if ( ...

  5. springboot 修改文件上传大小限制

    springboot 1.5.9文件上传大小限制spring:http:multipart:maxFileSize:50MbmaxRequestSize:50Mb springboot 2.0文件上传 ...

  6. javaweb基础(8)_HttpServletResponse生成验证码

    一.HttpServletResponse常见应用——生成验证码 1.1.生成随机图片用作验证码 生成图片主要用到了一个BufferedImage类,

  7. LINQ结合正则表达式查询文件系统

    string startFolder = @"D:\Program Files (x86)\Microsoft Visual Studio 12.0\"; IEnumerable& ...

  8. 什么是静态代码块?java中如何使用空参构造方法自动生成不同名字的对象,使用非静态的属性和静态属性有什么区别,原因是什么?如何理解static关键字

    静态代码块?类加载就执行,最先执行 class demo{ static int num; static{ num=10; num*=3; System.out.println("haha& ...

  9. linux 下使用 curl 访问带多参数,GET掉参数解决方案

    url 为 http://mywebsite.com/index.php?a=1&b=2&c=3 web形式下访问url地址,使用 $_GET是可以获取到所有的参数 curl  -s  ...

  10. 【概率dp 高斯消元】bzoj3270: 博物馆

    一类成环概率dp的操作模式 Description 有一天Petya和他的朋友Vasya在进行他们众多旅行中的一次旅行,他们决定去参观一座城堡博物馆.这座博物馆有着特别的样式.它包含由m条走廊连接的n ...