解题报告 之 POJ2135 Farm Tour

解题报告 之 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.

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.

Output

A single line containing the length of the shortest tour.

Sample Input

4 5
1 2 1
2 3 1
3 4 1
1 3 2
2 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 );
					}
					else
						dq.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;
}

昨天熬夜搞完WebServer,看来今天要复习一下计网和嵌入式和通信原理了。靠,,我绝对没有暴露我的专业背景。你们绝对猜不到我是啥专业的!

时间: 2024-10-18 01:06:17

解题报告 之 POJ2135 Farm Tour的相关文章

POJ2135 Farm Tour 【最小费用最大流】

Farm Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11782   Accepted: 4393 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

POJ2135:Farm Tour

http://poj.org/problem?id=2135 #include <iostream> #include <queue> #include <string.h> #include <stdlib.h> #include <algorithm> #include <math.h> #include <stdio.h> #define inf 0x3f3f3f3f using namespace std; int

POJ2135 Farm Tour 最小费用流

给出一个图,从一号节点去N号节点,再回来. 但是不能经过相同的边,即一条边最多只能够走一次. 求来回的总长度的最小值. 转化: 求1号到N号的2条没有公共边的路径,这样就相当于在这个图中所有边的容量都是1,现在要找2条增广路,得到的流量为2,就相当于求流量为2的最小费用流. 1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<vector> 5 6 using namespa

poj图论解题报告索引

最短路径: poj1125 - Stockbroker Grapevine(多源最短路径,floyd) poj1502 - MPI Maelstrom(单源最短路径,dijkstra,bellman-ford,spfa) poj1511 - Invitation Cards(单源来回最短路径,spfa邻接表) poj1797 - Heavy Transportation(最大边,最短路变形,dijkstra,spfa,bellman-ford) poj2240 - Arbitrage(汇率问题,

soj 1015 Jill&#39;s Tour Paths 解题报告

题目描述: 1015. Jill's Tour Paths Constraints Time Limit: 1 secs, Memory Limit: 32 MB Description Every year, Jill takes a bicycle tour between two villages. There are different routes she can take between these villages, but she does have an upper limit

leetCode解题报告5道题(十)

Disk Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2368    Accepted Submission(s): 333 Problem Description 有很多从磁盘读取数据的需求,包括顺序读取.随机读取.为了提高效率,需要人为安排磁盘读取.然而,在现实中,这种做法很复杂.我们考虑一个相对简单的场景.磁

POJ 2135 Farm Tour

Farm Tour Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on PKU. Original ID: 213564-bit integer IO format: %lld      Java class name: Main When FJ's friends visit him on the farm, he likes to show them around. His farm comprise

poj 1258 Agri-Net 解题报告

题目链接:http://poj.org/problem?id=1258 题目意思:给出 n 个 farm,每个farm 之间通过一定数量的fiber 相连,问使得所有farm 直接或间接连通的 最少 fiber 数是多少. 赤裸裸的最小生成树,用prim做的. 有个地方写错,wa 了 几次. 1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 const int farm_num = 10000

解题报告 之 POJ1149 PIGS

解题报告 之 POJ1149 PIGS Description Mirko works on a pig farm that consists of M locked pig-houses and Mirko can't unlock any pighouse because he doesn't have the keys. Customers come to the farm one after another. Each of them has keys to some pig-house