解题报告 之 POJ2135 Farm Tour
来源:互联网 发布:java线程安全类有哪些 编辑:程序博客网 时间:2024/04/29 16:37
解题报告 之 POJ2135 Farm Tour
Description
When FJ's friends visit him on the farm, he likes to show them around. His farm comprises N (1 <= N <= 1000) fields numbered 1..N, the first of which contains his house and the Nth of which contains the big barn. A total M (1 <= M <= 10000) paths that connect the fields in various ways. Each path connects two different fields and has a nonzero length smaller than 35,000.
To show off his farm in the best way, he walks a tour that starts at his house, potentially travels through some fields, and ends at the barn. Later, he returns (potentially through some fields) back to his house again.
He wants his tour to be as short as possible, however he doesn't want to walk on any given path more than once. Calculate the shortest tour possible. FJ is sure that some tour exists for any given farm.
To show off his farm in the best way, he walks a tour that starts at his house, potentially travels through some fields, and ends at the barn. Later, he returns (potentially through some fields) back to his house again.
He wants his tour to be as short as possible, however he doesn't want to walk on any given path more than once. Calculate the shortest tour possible. FJ is sure that some tour exists for any given farm.
Input
* Line 1: Two space-separated integers: N and M.
* Lines 2..M+1: Three space-separated integers that define a path: The starting field, the end field, and the path's length.
* Lines 2..M+1: Three space-separated integers that define a path: The starting field, the end field, and the path's length.
Output
A single line containing the length of the shortest tour.
Sample Input
4 51 2 12 3 13 4 11 3 22 4 2
Sample Output
6
题目大意:给你一个无向图,有n个节点编号1~n,m条边。且起点为1,终点为n。给出每条边的长度,并要求每条边只能走一次,问你从起点走到终点再从终点走回起点的最短路是多少?
分析:首先直观的感觉到,如果可以重复走那么直接上SPFA即可。但是这道题要求每天边只能走一次,那么最短路算法就无效了。所以我们该怎么办呢?建议你先参考另一篇博文,这是边不重复最短路模型,这道题似乎是该模型的最小费用流升级版。
ZOJ 2760 How Many Shortest Path
http://blog.csdn.net/maxichu/article/details/45151399
那么至此我已经假设你明白边不重复最短路了。通过最大流我们可以找到有几天边不重复的最短路,但是此题并不要求是两条最短路而是总长度最短即可。所以我们必须引入最小费用流来解题了。最小费用流的理论建议看《挑战》,但是感觉《挑战》的代码实现比较凌乱不是很适合我这种小白,于是我看懂了之后自创了一个模板(赞起来。囧)。。那么此题的其实就是最基本的一个最小费用流了。
首先超级源点连接节点1,负载为2,费用为0。然后根据输入建图即可,节点n与超级汇点连接,负载为2,费用为0。然后跑一条最大流为2的最小费用流即是答案。我的模板中采用了《挑战》的h标号法,但此题并不存在负权边,我只是为了存个模板。。。
上代码:
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<queue>#include<deque>using namespace std;const int MAXN = 90010;const int MAXM = 910000;const int INF = 0x3f3f3f3f;struct Edge{int from, to, cap, next, cost;};Edge edge[MAXM];int prevv[MAXN];int preve[MAXN];int dist[MAXN];int head[MAXN];int h[MAXN]; //标号数组int src, des, cnt;void addedge( int from, int to, int cap, int cost ){edge[cnt].from = from;edge[cnt].to = to;edge[cnt].cap = cap;edge[cnt].cost = cost;edge[cnt].next = head[from];head[from] = cnt++;swap( from, to );edge[cnt].from = from;edge[cnt].to = to;edge[cnt].cap = 0;edge[cnt].cost = -cost;edge[cnt].next = head[from];head[from] = cnt++;}int SPFA( ){deque<int> dq;bool inqueue[MAXN];memset( dist, INF, sizeof dist );memset( inqueue, 0, sizeof inqueue );dq.push_back( src );inqueue[src] = 1;dist[src] = 0;while(!dq.empty()){int u = dq.front();dq.pop_front();inqueue[u] = 0;for(int i = head[u]; i != -1; i = edge[i].next){int v = edge[i].to;if(edge[i].cap > 0 && dist[u] + edge[i].cost +h[u]-h[v]< dist[v]){dist[v] = dist[u] + edge[i].cost + h[u] - h[v];prevv[v] = u;preve[v] = i;if(!inqueue[v]){if(!dq.empty() && dist[v] <= dist[dq.front()]){dq.push_front( v );}elsedq.push_back( v );}}}}return 0;}int min_cost_flow(int f,int n){memset( h, 0, sizeof h );int cost = 0;while(f > 0){SPFA();if(dist[des] == INF){return -1;}for(int u = 1; u <= n; u++)h[u] += dist[u];h[des] += dist[des];int d = f;for(int i = des; i != src; i = prevv[i]){d = min( d, edge[preve[i]].cap );}//此处循环比较鸡肋因为负载都为1。f -= d;cost += d*h[des];for(int i = des; i != src; i = prevv[i]){edge[preve[i]].cap -= d;edge[preve[i] ^ 1].cap += d;}}return cost;}int main( ){int n, m;src = 0;des = 90005;while(cin >> n >> m){memset( head, -1, sizeof head );cnt = 0;int a, b, c;for(int i = 1; i <= m; i++){cin >> a >> b >> c;addedge( a, b, 1, c );addedge( b, a, 1, c );}addedge( src, 1, 2, 0 );addedge( n, des, 2, 0 );cout << min_cost_flow(2,n) << endl;}return 0;}
1 0
- 解题报告 之 POJ2135 Farm Tour
- poj2135 - Farm Tour
- poj2135 Farm Tour
- poj2135--Farm Tour
- poj2135 Farm Tour
- POJ2135 Farm Tour (mcmf)
- POJ2135-Farm Tour
- 【poj2135】Farm Tour
- POJ2135 Farm Tour
- POJ2135: Farm Tour 题解
- POJ2135 Farm Tour
- POJ2135:Farm Tour
- poj2135——Farm Tour
- poj 2135 Farm Tour 解题报告
- 【POJ2135】Farm Tour 最小费用最大流
- Poj2135 Farm Tour (最小费用流)
- Poj2135 Farm Tour 最小费用流
- poj2135 Farm Tour 最小费用最大流
- node.js入门【编一个小web服务器】
- 1、Distribution And Trade
- android控件的继承关系及控件功能大全
- [C++]LeetCode 3: Longest Substring Without Repeating Characters(最长不重复子串)
- <Head First Java>学习笔记--第五章:编写程序
- 解题报告 之 POJ2135 Farm Tour
- Linux输入子系统框架
- android java 遍历Header[] header
- 模板概述
- ArrayList源码解析(基于JDK1.6)
- myeclipse快捷键使用
- 周记——20150427
- Unity动态加载和内存管理
- 栈和其在二进制转换为十进制的应用(c语言)