[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条),所以无解。

——代码

1 #include <map> 2 #include <queue> 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 #define N 10001 7 #define M 1000001 8 #define min(x, y) ((x) < (y) ? (x) : (y)) 9 10 int n, m, cnt, flow, ans, s, t; 11 std::string str[1001], s1, s2; 12 std::map <std::string, int> p; 13 int head[N], to[M], val[M], cost[M], next[M], dis[N], pre[N]; 14 bool vis[N]; 15 16 inline void add(int x, int y, int z, int c) 17 24 25 inline bool spfa() 26 50 } 51 } 52 } 53 return pre[t] ^ 1; 54 } 55 56 int main() 57 71 for(i = 1; i <= m; i++) 72 80 while(spfa()) 81 89 flow += d; 90 ans += dis[t] * d; 91 } 92 if(flow ^ 2) 93 97 printf("%d\n", ans 2); 98 memset(vis, 0, sizeof(vis)); 99 vis[1] = vis[0] = 1; 100 std::cout << str[1] << std::endl; 101 for(i = head[s + n]; i ^ 1; i = next[i]) 102 if(!val[i] && !vis[to[i]]) 103 115 } 116 break; 117 } 118 for(i = head[n]; i ^ 1; i = next[i]) 119 if(!val[i ^ 1] && !vis[to[i] n]) 120 132 } 133 break; 134 } 135 std::cout << str[1] << std::endl; 136 return 0; 137 }
View Code



上一篇:[luoguP2774] 方格取数问题(最大点权独立集)

下一篇:[cogs729]圆桌问题(最大流)


最小费用最大流 最大流 网络流
Copyright © 2002-2019 k262电脑网 www.k262.cn 皖ICP备2020016292号
温馨提示:部分文章图片数据来源与网络,仅供参考!版权归原作者所有,如有侵权请联系删除!QQ:251442993 热门搜索 网站地图