POJ-2135 Farm Tour---最小费用最大流模板题(构图)
题目链接:
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的情况,所以放心的敲模板吧。
#include<iostream>
#include<vector>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = + ;
struct edge
{
int u, v, c, f, cost;
edge(int u, int v, int c, int f, int cost):u(u), v(v), c(c), f(f), cost(cost){}
};
vector<edge>e;
vector<int>G[maxn];
int a[maxn];//找增广路每个点的水流量
int p[maxn];//每次找增广路反向记录路径
int d[maxn];//SPFA算法的最短路
int inq[maxn];//SPFA算法是否在队列中
int n, m;
void init(int n)
{
for(int i = ; i <= n; i++)G[i].clear();
e.clear();
}
void addedge(int u, int v, int c, int cost)
{
e.push_back(edge(u, v, c, , cost));
e.push_back(edge(v, u, , , -cost));
int m = e.size();
G[u].push_back(m - );
G[v].push_back(m - );
}
bool bellman(int s, int t, int& flow, long long & cost)
{
for(int i = ; i <= n + ; i++)d[i] = INF;//Bellman算法的初始化
memset(inq, , sizeof(inq));
d[s] = ;inq[s] = ;//源点s的距离设为0,标记入队
p[s] = ;a[s] = INF;//源点流量为INF(和之前的最大流算法是一样的) queue<int>q;//Bellman算法和增广路算法同步进行,沿着最短路拓展增广路,得出的解一定是最小费用最大流
q.push(s);
while(!q.empty())
{
int u = q.front();
q.pop();
inq[u] = ;//入队列标记删除
for(int i = ; i < G[u].size(); i++)
{
edge & now = e[G[u][i]];
int v = now.v;
if(now.c > now.f && d[v] > d[u] + now.cost)
//now.c > now.f表示这条路还未流满(和最大流一样)
//d[v] > d[u] + e.cost Bellman 算法中边的松弛
{
d[v] = d[u] + now.cost;//Bellman 算法边的松弛
p[v] = G[u][i];//反向记录边的编号
a[v] = min(a[u], now.c - now.f);//到达v点的水量取决于边剩余的容量和u点的水量
if(!inq[v]){q.push(v);inq[v] = ;}//Bellman 算法入队
}
}
}
if(d[t] == INF)return false;//找不到增广路
flow += a[t];//最大流的值,此函数引用flow这个值,最后可以直接求出flow
cost += (long long)d[t] * (long long)a[t];//距离乘上到达汇点的流量就是费用
for(int u = t; u != s; u = e[p[u]].u)//逆向存边
{
e[p[u]].f += a[t];//正向边加上流量
e[p[u] ^ ].f -= a[t];//反向边减去流量 (和增广路算法一样)
}
return true;
}
int MincostMaxflow(int s, int t, long long & cost)
{
cost = ;
int flow = ;
while(bellman(s, t, flow, cost));//由于Bellman函数用的是引用,所以只要一直调用就可以求出flow和cost
return flow;//返回最大流,cost引用可以直接返回最小费用
}
int main()
{
cin >> n >> m;
int u, v, c;
for(int i = ; i < m; i++)
{
cin >> u >> v >> c;
addedge(u, v, , c);
addedge(v, u, , c);
}
int s = , t = n + ; addedge(s, , , );//超级源点,边可通过两次,所以流量设成2,费用为0
addedge(n, t, , );//超级汇点,边可通过两次,流量设成2,费用为0
long long ans;
MincostMaxflow(s, t, ans);
cout<<ans<<endl;
return ;
}
POJ-2135 Farm Tour---最小费用最大流模板题(构图)的更多相关文章
- poj 2135 Farm Tour 最小费用最大流建图跑最短路
题目链接 题意:无向图有N(N <= 1000)个节点,M(M <= 10000)条边:从节点1走到节点N再从N走回来,图中不能走同一条边,且图中可能出现重边,问最短距离之和为多少? 思路 ...
- POJ 2135 Farm Tour [最小费用最大流]
题意: 有n个点和m条边,让你从1出发到n再从n回到1,不要求所有点都要经过,但是每条边只能走一次.边是无向边. 问最短的行走距离多少. 一开始看这题还没搞费用流,后来搞了搞再回来看,想了想建图不是很 ...
- poj 2351 Farm Tour (最小费用最大流)
Farm Tour Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 17230 Accepted: 6647 Descri ...
- Farm Tour(最小费用最大流模板)
Farm Tour Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 18150 Accepted: 7023 Descri ...
- [poj] 1235 Farm Tour || 最小费用最大流
原题 费用流板子题. 费用流与最大流的区别就是把bfs改为spfa,dfs时把按deep搜索改成按最短路搜索即可 #include<cstdio> #include<queue> ...
- POJ2135 Farm Tour —— 最小费用最大流
题目链接:http://poj.org/problem?id=2135 Farm Tour Time Limit: 1000MS Memory Limit: 65536K Total Submis ...
- 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 ...
- POJ2135 最小费用最大流模板题
练练最小费用最大流 此外此题也是一经典图论题 题意:找出两条从s到t的不同的路径,距离最短. 要注意:这里是无向边,要变成两条有向边 #include <cstdio> #include ...
- 【网络流#2】hdu 1533 - 最小费用最大流模板题
最小费用最大流,即MCMF(Minimum Cost Maximum Flow)问题 嗯~第一次写费用流题... 这道就是费用流的模板题,找不到更裸的题了 建图:每个m(Man)作为源点,每个H(Ho ...
- 2018牛客网暑期ACM多校训练营(第五场) E - room - [最小费用最大流模板题]
题目链接:https://www.nowcoder.com/acm/contest/143/E 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K ...
随机推荐
- java模拟简易按键精灵
很多小伙伴们都有过抢课的经历,有时候抢不到自己想上的课,只能盼望有人退选,可是很多时候别人退选了,但是很快又被别人抢走了,我们不可能时刻盯着电脑, 这时候如果有一个抢课的程序岂不是很棒.. 出于这个目 ...
- Unix Tutorial Four
4.1 wildcards 通配符 * 通配符,配对1个或以上字符 ?通配符,只配对1个 4.2 Filename conventions 文件名约定 注意: 1. 目录是特殊的文件,故文件名的命名规 ...
- 对zabbix监控磁盘性能的补充
原因 在上一篇文章中,我写了完整的磁盘监控步骤,希望对大家有所帮助.但是这里还需要作出一点补充. 根据上一篇文章的内容,我是使用iostat命令不停的收集磁盘的信息,然后写入到/tmp/iostat_ ...
- 根据T-Code查看用户出口的代码
在此非常非常感谢源作者,这段代码真的非常非常有用好用! REPORT YLBTEST. TABLES : tstc, "SAP Transaction Codes(SAP 事务代 ...
- 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 ...
- CF987B High School: Become Human 数学
题意翻译 题目大意 输入一个 xxx ,一个 yyy ,求是 xyx^yxy 大还是 yxy^xyx 大. (1≤x,y≤109)(1≤x,y≤10^9)(1≤x,y≤109) 输入输出格式 输入格式 ...
- windows驱动环境配置vs2010+wdk7600
安装wdk后 要勾选集成VSIX选项到vs里面,不然vs里面新建项目时候找不到windows Driver 最简单的方式是安装wdk7600+vs2010+VisualDDK-1.5.7 这三个软件 ...
- BigDecimal默认用四舍五入方式
import java.math.BigDecimal; target.setWeight(source.getWeight().setScale(3, BigDecimal.ROUND_HALF_U ...
- 牛客网Java刷题知识点之全局变量(又称成员变量,分为类变量和实例变量)、局部变量、静态变量(又称为类变量)
不多说,直接上干货! 定义类其实就是在定义类中的成员.成员:成员变量<-->属性,成员函数<-->行为. 局部变量在方法内部声明,并且只能在方法内部使用,在外层的方法被调用时被 ...
- 你还在为UiPath课程考试发愁吗?
刚开始学UiPath的时候,课程的考试难倒了很多人,有语言的原因也有对课程理解的原因,记忆中好像有一课考了5次估计,由于题库也就那么多,只要你努力考,总会过的. 学会了RPA的自动化工具,能否自动化答 ...