题目链接:

https://vjudge.net/problem/POJ-2135

题目大意:

主人公要从1号走到第N号点,再重N号点走回1号点,同时每条路只能走一次。
这是一个无向图。输入数据第一行是2个是N和M。N为点的数量,M为路径个数。
接下来M行是边的数据,每行输入3个数,边的两个端点a,b和边的长度v。
要你输出来回最短的路径长度。
题目确保存在来回的不重复路径

解题思路:

这题可以转换成网络流的费用流。

来回并且路径不相同就相当于有用两条从1到N的路径。

把路径长度当成网络流里面每个流的费用,流量都设置成1这样就代表每条路径只能使用1次。增加2个点,源点和汇点,因为来回,就把源点到1建立一条流,流量为2(来回)费用为0,同样N到汇点建立一条流,流量为2费用为0。(保证只有两条路从源点到汇点,就是答案的解)这样一个网络流就出来了。

这里输入一条边要建4条边,首先建a->b的有向边,要同时建立反向边,再建b->a的有向边,一样建立反向边。

其他的就是模板了

注意:有可能会有这样一个问题,一条无向边拆分成两条有向边,有没有可能会把这两条有向边都走了呢,答案是否定的,因为求的是最小费用,如果一条边正向反向均走了一次,那么总流量为0,而且还有额外的费用,而我们算法的策略是每次都取最短路(也就是最小费用)找增广路,所以不可能找出费用为正数流量为0的情况,所以放心的敲模板吧。

  1. #include<iostream>
  2. #include<vector>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. using namespace std;
  7. const int INF = 0x3f3f3f3f;
  8. const int maxn = + ;
  9. struct edge
  10. {
  11. int u, v, c, f, cost;
  12. edge(int u, int v, int c, int f, int cost):u(u), v(v), c(c), f(f), cost(cost){}
  13. };
  14. vector<edge>e;
  15. vector<int>G[maxn];
  16. int a[maxn];//找增广路每个点的水流量
  17. int p[maxn];//每次找增广路反向记录路径
  18. int d[maxn];//SPFA算法的最短路
  19. int inq[maxn];//SPFA算法是否在队列中
  20. int n, m;
  21. void init(int n)
  22. {
  23. for(int i = ; i <= n; i++)G[i].clear();
  24. e.clear();
  25. }
  26. void addedge(int u, int v, int c, int cost)
  27. {
  28. e.push_back(edge(u, v, c, , cost));
  29. e.push_back(edge(v, u, , , -cost));
  30. int m = e.size();
  31. G[u].push_back(m - );
  32. G[v].push_back(m - );
  33. }
  34. bool bellman(int s, int t, int& flow, long long & cost)
  35. {
  36. for(int i = ; i <= n + ; i++)d[i] = INF;//Bellman算法的初始化
  37. memset(inq, , sizeof(inq));
  38. d[s] = ;inq[s] = ;//源点s的距离设为0,标记入队
  39. p[s] = ;a[s] = INF;//源点流量为INF(和之前的最大流算法是一样的)
  40.  
  41. queue<int>q;//Bellman算法和增广路算法同步进行,沿着最短路拓展增广路,得出的解一定是最小费用最大流
  42. q.push(s);
  43. while(!q.empty())
  44. {
  45. int u = q.front();
  46. q.pop();
  47. inq[u] = ;//入队列标记删除
  48. for(int i = ; i < G[u].size(); i++)
  49. {
  50. edge & now = e[G[u][i]];
  51. int v = now.v;
  52. if(now.c > now.f && d[v] > d[u] + now.cost)
  53. //now.c > now.f表示这条路还未流满(和最大流一样)
  54. //d[v] > d[u] + e.cost Bellman 算法中边的松弛
  55. {
  56. d[v] = d[u] + now.cost;//Bellman 算法边的松弛
  57. p[v] = G[u][i];//反向记录边的编号
  58. a[v] = min(a[u], now.c - now.f);//到达v点的水量取决于边剩余的容量和u点的水量
  59. if(!inq[v]){q.push(v);inq[v] = ;}//Bellman 算法入队
  60. }
  61. }
  62. }
  63. if(d[t] == INF)return false;//找不到增广路
  64. flow += a[t];//最大流的值,此函数引用flow这个值,最后可以直接求出flow
  65. cost += (long long)d[t] * (long long)a[t];//距离乘上到达汇点的流量就是费用
  66. for(int u = t; u != s; u = e[p[u]].u)//逆向存边
  67. {
  68. e[p[u]].f += a[t];//正向边加上流量
  69. e[p[u] ^ ].f -= a[t];//反向边减去流量 (和增广路算法一样)
  70. }
  71. return true;
  72. }
  73. int MincostMaxflow(int s, int t, long long & cost)
  74. {
  75. cost = ;
  76. int flow = ;
  77. while(bellman(s, t, flow, cost));//由于Bellman函数用的是引用,所以只要一直调用就可以求出flow和cost
  78. return flow;//返回最大流,cost引用可以直接返回最小费用
  79. }
  80. int main()
  81. {
  82. cin >> n >> m;
  83. int u, v, c;
  84. for(int i = ; i < m; i++)
  85. {
  86. cin >> u >> v >> c;
  87. addedge(u, v, , c);
  88. addedge(v, u, , c);
  89. }
  90. int s = , t = n + ;
  91.  
  92. addedge(s, , , );//超级源点,边可通过两次,所以流量设成2,费用为0
  93. addedge(n, t, , );//超级汇点,边可通过两次,流量设成2,费用为0
  94. long long ans;
  95. MincostMaxflow(s, t, ans);
  96. cout<<ans<<endl;
  97. return ;
  98. }

POJ-2135 Farm Tour---最小费用最大流模板题(构图)的更多相关文章

  1. poj 2135 Farm Tour 最小费用最大流建图跑最短路

    题目链接 题意:无向图有N(N <= 1000)个节点,M(M <= 10000)条边:从节点1走到节点N再从N走回来,图中不能走同一条边,且图中可能出现重边,问最短距离之和为多少? 思路 ...

  2. POJ 2135 Farm Tour [最小费用最大流]

    题意: 有n个点和m条边,让你从1出发到n再从n回到1,不要求所有点都要经过,但是每条边只能走一次.边是无向边. 问最短的行走距离多少. 一开始看这题还没搞费用流,后来搞了搞再回来看,想了想建图不是很 ...

  3. poj 2351 Farm Tour (最小费用最大流)

    Farm Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17230   Accepted: 6647 Descri ...

  4. Farm Tour(最小费用最大流模板)

    Farm Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18150   Accepted: 7023 Descri ...

  5. [poj] 1235 Farm Tour || 最小费用最大流

    原题 费用流板子题. 费用流与最大流的区别就是把bfs改为spfa,dfs时把按deep搜索改成按最短路搜索即可 #include<cstdio> #include<queue> ...

  6. POJ2135 Farm Tour —— 最小费用最大流

    题目链接:http://poj.org/problem?id=2135 Farm Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submis ...

  7. TZOJ 1513 Farm Tour(最小费用最大流)

    描述 When FJ's friends visit him on the farm, he likes to show them around. His farm comprises N (1 &l ...

  8. POJ2135 最小费用最大流模板题

    练练最小费用最大流 此外此题也是一经典图论题 题意:找出两条从s到t的不同的路径,距离最短. 要注意:这里是无向边,要变成两条有向边 #include <cstdio> #include ...

  9. 【网络流#2】hdu 1533 - 最小费用最大流模板题

    最小费用最大流,即MCMF(Minimum Cost Maximum Flow)问题 嗯~第一次写费用流题... 这道就是费用流的模板题,找不到更裸的题了 建图:每个m(Man)作为源点,每个H(Ho ...

  10. 2018牛客网暑期ACM多校训练营(第五场) E - room - [最小费用最大流模板题]

    题目链接:https://www.nowcoder.com/acm/contest/143/E 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K ...

随机推荐

  1. PAT1089【归并排序】

    这题略...恶心.. 他说归并排序依次是相邻有序两块合并,而一向打惯了递归??? #include <bits/stdc++.h> using namespace std; typedef ...

  2. 用vue写一个仿简书的轮播图

    原文地址:用vue写一个仿简书的轮播图 先展示最终效果: Vue的理念是以数据驱动视图,所以拒绝通过改变元素的margin-top来实现滚动效果.写好css样式,只需改变每张图片的class即可实现轮 ...

  3. 在pom包中添加spring-boot-starter-test包引用

    有很多网友会时不时的问我,spring boot项目如何测试,如何部署,在生产中有什么好的部署方案吗?这篇文章就来介绍一下spring boot 如何开发.调试.打包到最后的投产上线. 开发阶段 单元 ...

  4. C#正则表达式快速入门

    作者将自己在学习正则表达式中的心得和笔记作了个总结性文章,希望对初学C#正则表达式的读者有帮助. [内容] 什么是正则表达式 涉及的基本的类 正则表达式基础知识 构建表达式基本方法 编写一个检验程序 ...

  5. UVA - 12563 Jin Ge Jin Qu hao (01背包)

    InputThe first line contains the number of test cases T (T ≤ 100). Each test case begins with two po ...

  6. MarkDown基础语法大全

    一.MarkDown是什么? Markdown是一种轻量级的「标记语言」,创始人为约翰·格鲁伯,用简洁的语法代替排版,目前被越来越多的知识工作者.写作爱好者.程序员或研究员广泛使用.其常用的标记符号不 ...

  7. [Leetcode]007. Reverse Integer

    public class Solution { public int reverse(int x) { long rev=0; while(x!=0){ rev = rev*10+x%10; x=x/ ...

  8. 华东交通大学2017年ACM“双基”程序设计竞赛 1001

    Problem Description 最近流行吃鸡,那就直接输出一行"Winner winner ,chicken dinner!"(没有双引号)模板代码:#include &l ...

  9. .NET Memcached Client 扩展获取所有缓存Key

    .NET Memcached Client默认实现中并没有获取所有已经缓存Key的方法,但在业务中有时候需求中需要通过正则删除符合条件的缓存内容,所以就要通过读取已经缓存Key进行相关的匹配,然后删除 ...

  10. 11-----broder(边框)

    边框 border:边框的意思,描述盒子的边框 边框有三个要素: 粗细 线性样式 颜色 如果颜色不写,默认是黑色.如果粗细不写,不显示边框.如果只写线性样式,默认的有上下左右 3px的宽度,实体样式, ...