poj 2631: Roads in the North (树的直径)

题目来源:http://poj.org/problem?id=2631

Roads in the North

Time Limit: 1000MS

Memory Limit: 65536K

Total Submissions: 3351

Accepted: 1655

Description

Building and maintaining roads among communitiesin the far North is an expensive business. With this in mind, the roads arebuild such that there is only one route from a village to a village that doesnot pass through some other village twice. 
Given is an area in the far North comprising a number of villages and roadsamong them such that any village can be reached by road from any other village.Your job is to find the road distance between the two most remote villages inthe area. 

The area has up to 10,000 villages connected by road segments. The villages arenumbered from 1. 

Input

Input to the problem is a sequence of lines,each containing three positive integers: the number of a village, the number ofa different village, and the length of the road segment connecting the villagesin kilometers. All road segments are two-way.

Output

You are to output a single integer: the roaddistance between the two most remote villages in the area.

Sample Input

5 1 6
1 4 5
6 3 9
2 6 8
6 1 7

SampleOutput

22

Source

The UofA Local 1999.10.16

-----------------------------------------------------

解题思路

两次广度优先搜索

第一次从任一点开始,广度优先搜索找到从该点出发的最长路,记下路终点s

第二次从s点开始,广度优先搜索找到从s点出发的最长路,此即直径

该算法由以下定理保证:

树的直径定义为树中的最长简单道路,

证明:从任意节点出发的最长简单道路终点,一定在树的直径上

-----------------------------------------------------

代码

//Roads in the North
//Time Limit: 1000MS		Memory Limit: 65536K
//Description
//
//Building and maintaining roads among communities in the far North is an expensive business. With this in mind, the roads are build such that there is only one route from a village to a village that does not pass through some other village twice. 
//Given is an area in the far North comprising a number of villages and roads among them such that any village can be reached by road from any other village. Your job is to find the road distance between the two most remote villages in the area. 
//
//The area has up to 10,000 villages connected by road segments. The villages are numbered from 1. 
//Input
//
//Input to the problem is a sequence of lines, each containing three positive integers: the number of a village, the number of a different village, and the length of the road segment connecting the villages in kilometers. All road segments are two-way.
//Output
//
//You are to output a single integer: the road distance between the two most remote villages in the area.
//Sample Input
//
//5 1 6
//1 4 5
//6 3 9
//2 6 8
//6 1 7
//Sample Output
//
//22
//Source
//
//The UofA Local 1999.10.16

// 求树的直径
// 从任意节点开始,宽搜找最长路得到直径的一个节点s
// 从节点s开始宽搜找最长路得直径

#include<fstream>
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;

const int MAX = 20003;

void bfs(int s, vector<int> *aim, vector<int> *weight, int *len)
{
	deque<int> q;								// 双端队列
	bool mark[MAX] = {};						// 是否被标记过,初始化为否
	int p = s ,i = 0, pp = s;
	q.push_back(s);								// s入队
	mark[s] = true;
	len[s] = 0;									// s到s的距离为0
	while(!q.empty())							// 当队列不空
	{
		p = q.front();							// 取队首元素
		for (i=0; i<aim[p].size(); i++)			// 将所有没有访问的后继节点入队
		{
			pp = aim[p].at(i);					// p的后继节点
			if (!mark[pp])						// 如果没有访问过
			{
				mark[pp] = true;				// 访问它
				q.push_back(pp);				// 入队
				len[pp] = len[p] + weight[p].at(i);	// 更新路径长度
			}

		}
		q.pop_front();
	}

}


int main()
{
#ifndef ONLINE_JUDGE
	ifstream fin("poj2631.txt");
	int x,y,w,n=1;								// n统计节点个数,边数=节点数-1,故从1开始计数
	// 用正向表存储边
	vector<int> aim[MAX] = {};					// 端点向量
	vector<int> weight[MAX] = {};				// 权值向量
	while (fin >> x >> y >> w)
	{
		x--; y--;								// 下标从0开始
		aim[x].push_back(y);
		weight[x].push_back(w);
		aim[y].push_back(x);
		weight[y].push_back(w);
		n++;
	}
	fin.close();
	int len[MAX] = {};
	bfs(0, aim, weight, len);
	int i = 0, max = 0, s = 0;
	for (i=0; i<n; i++)
	{
		if (len[i] > max)
		{
			s = i;
			max = len[i];
		}
	}
	memset(len,0,sizeof(len));
	max = 0;
	bfs(s, aim, weight, len);
	for (i=0; i<n; i++)
	{
		if (len[i] > max)
		{
			s = i;
			max = len[i];
		}
	}
	cout << len[s];
	return 0;
#endif
#ifdef ONLINE_JUDGE
	int x,y,w,n=1;								// n统计节点个数,边数=节点数-1,故从1开始计数
	// 用正向表存储边
	vector<int> aim[MAX] = {};					// 端点向量
	vector<int> weight[MAX] = {};				// 权值向量
	while (cin >> x >> y >> w)
	{
		x--; y--;								// 下标从0开始
		aim[x].push_back(y);
		weight[x].push_back(w);
		aim[y].push_back(x);
		weight[y].push_back(w);
		n++;
	}
	int len[MAX] = {};
	bfs(0, aim, weight, len);
	int i = 0, max = 0, s = 0;
	for (i=0; i<n; i++)
	{
		if (len[i] > max)
		{
			s = i;
			max = len[i];
		}
	}
	memset(len,0,sizeof(len));
	max = 0;
	bfs(s, aim, weight, len);
	for (i=0; i<n; i++)
	{
		if (len[i] > max)
		{
			s = i;
			max = len[i];
		}
	}
	cout << len[s];
	return 0;
#endif
}

猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/80304914