题目链接:http://poj.org/problem?id=2631

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.
 
题目大意:给你一棵树,求树上最远的两点距离为多少。(题目描述比较奇葩,你可以认为点数等于边数+1,所有运算不会超过2^31-1)
思路:从任意一点开始,找到离这个点最远的点x。再从x开始做单源最短路,离x最远的点和x就是这棵树的最远点对。(当然基于树的分治也是可以做的)
证明(参考DISCUSS):
设最长链是MN->已知[1]
设由A开始DFS得到最长路为AB->已知[2]
结论[1] MN与AB有公共点.否则MN<AM+AN<=AM+AB=BM 与已知[1]矛盾
结论[2] B是最长链的一个端点.否则由结论[1] 设K是AB上距B最近且在MN上的点 则MN=MK+KN=MK+AN-AK<=MK+AB-AK=MK+BK=BM 当取等号时MB与MN等长 符合结论[2] 否则与已知[1]矛盾 [这里假定了A不在NK上.若A在NK上 只须将上面式子中MN交换位置即可 不影响结论]
结论[3] 从B开始DFS得到的最长路径是一条最长链.由结论[2].B是最长链的一端
至此证毕

代码(0MS):

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std; const int MAXN = ;
const int MAXE = ; int dis[MAXN], head[MAXN];
int to[MAXE], next[MAXE], cost[MAXE];
int n, ecnt; void init() {
memset(head, -, sizeof(head));
ecnt = ;
} void add_edge(int u, int v, int c) {
to[ecnt] = v; cost[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; cost[ecnt] = c; next[ecnt] = head[v]; head[v] = ecnt++;
} int bfs(int st) {
memset(dis, 0x3f, sizeof(dis));
queue<int> que; que.push(st);
dis[st] = ;
while(!que.empty()) {
int u = que.front(); que.pop();
for(int p = head[u]; ~p; p = next[p]) {
int &v = to[p];
if(dis[v] > dis[u] + cost[p]) {
dis[v] = dis[u] + cost[p];
que.push(v);
}
}
}
int ed = st;
for(int i = ; i <= n; ++i)
if(dis[i] > dis[ed]) ed = i;
return ed;
} int main() {
init();
n = ;
int u, v, c;
while(scanf("%d%d%d", &u, &v, &c) != EOF) {
add_edge(u, v, c);
++n;
}
u = bfs();
v = bfs(u);
printf("%d\n", dis[v]);
}

————————————————————————————————时间的分割线————————————————————————————————————————————————

后记(2014-7-26):

当然这题还可以树DP,之前觉得麻烦用了上面的解法。现在有一个比较高大上的写法,边权是负数的时候也适用(据说上面的做法边权有负数就没用了,我懒得验证了有兴趣去验证一下吧……)。

思路很简单,树的直径必然是树上某一个点开始往下的最长链和次长链之和。而实现的时候只要保留最长链的大小就可以了,比较简单不讲了看代码就好。

代码(16MS):

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std; const int MAXV = ;
const int MAXE = ; int head[MAXV];
int to[MAXE], next[MAXE], cost[MAXE];
int n, ecnt; void init() {
memset(head, -, sizeof(head));
ecnt = ;
} void add_edge(int u, int v, int c) {
to[ecnt] = v; cost[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; cost[ecnt] = c; next[ecnt] = head[v]; head[v] = ecnt++;
} int dfs(int u, int f, int &ans) {
int maxdep = ;
for(int p = head[u]; ~p; p = next[p]) {
int &v = to[p];
if(v == f) continue;
int tmp = dfs(v, u, ans) + cost[p];
ans = max(ans, maxdep + tmp);
maxdep = max(tmp, maxdep);
}
return maxdep;
} int main() {
init();
n = ;
int u, v, c;
while(scanf("%d%d%d", &u, &v, &c) != EOF) {
add_edge(u, v, c);
++n;
}
int ans = ;
dfs(, , ans);
printf("%d\n", ans);
}

POJ 2631 Roads in the North(求树的直径,两次遍历 or 树DP)的更多相关文章

  1. POJ 2631 Roads in the North(树的直径)

    POJ 2631 Roads in the North(树的直径) http://poj.org/problem? id=2631 题意: 有一个树结构, 给你树的全部边(u,v,cost), 表示u ...

  2. poj 2631 Roads in the North

    题目连接 http://poj.org/problem?id=2631 Roads in the North Description Building and maintaining roads am ...

  3. poj 2631 Roads in the North (自由树的直径)

    Roads in the North Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4513   Accepted: 215 ...

  4. poj 2631 Roads in the North【树的直径裸题】

    Roads in the North Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2359   Accepted: 115 ...

  5. POJ 2631 Roads in the North (模板题)(树的直径)

    <题目链接> 题目大意:求一颗带权树上任意两点的最远路径长度. 解题分析: 裸的树的直径,可由树形DP和DFS.BFS求解,下面介绍的是BFS解法. 在树上跑两遍BFS即可,第一遍BFS以 ...

  6. POJ 2631 Roads in the North (树的直径)

    题意: 给定一棵树, 求树的直径. 分析: 两种方法: 1.两次bfs, 第一次求出最远的点, 第二次求该点的最远距离就是直径. 2.同hdu2196的第一次dfs, 求出每个节点到子树的最长距离和次 ...

  7. POJ 2631 Roads in the North (求树的直径)

    Description Building and maintaining roads among communities in the far North is an expensive busine ...

  8. 题解报告:poj 2631 Roads in the North(最长链)

    Description Building and maintaining roads among communities in the far North is an expensive busine ...

  9. POJ [P2631] Roads in the North

    树的直径 树的直径求法: 任取一点u,找到树上距u最远的点s 找到树上距s点最远的点t,s->t的距离即为所求 #include <iostream> #include <cs ...

随机推荐

  1. JavaScript面向对象(封装)

    阮一峰的网络日志 1.生成实例对象的原始模式 var People = { name : '', age : '' } 根据这个原型对象生成两个实例对象 var people1 = {}; peopl ...

  2. 将jquery.qqFace.js表情转换成微信的字符码

    jquery.qqFace.js使用方法 引用 <script src="~/Content/qqFace/js/jquery.qqFace.js?v=3"></ ...

  3. GitHub Desktop 拉取 GitHub上 Tag 版本代码

    一直在使用 GitHub Desktop 图形化 git 管理工具,统一项目框架版本时需要切换到ThinkPHP Tag 分支版本,步骤如下, 1,先在 GitHub 中找到需要的版本,点进去 2,点 ...

  4. linux中删除文件内空白行的几种方法。

    linux中删除文件内空白行的几种方法 有时你可能需要在 Linux 中删除某个文件中的空行.如果是的,你可以使用下面方法中的其中一个.有很多方法可以做到,但我在这里只是列举一些简单的方法. 你可能已 ...

  5. 【Java】集合概述Collection、Map

    Java集合分为Collection和Map,Collection又分为List.Set. List中有ArrayList.LinkedList和Vector:Set中又分为HashSet和TreeS ...

  6. 公司内部搭建git服务器

    前言 因为gitHub上的项目是公开的,不适合公司内部项目放在上面,而私人的需要收费,这绝非是我们愿意的.所以找了个跟gitHub很相似,但是又免费的gitLab.现在将搭建gitLab过程记录一下留 ...

  7. 【C】关键字void的用法

    void有两种功能 [1]没有 [2]任意类型 void出现的位置不同会有不同的解释 [1]void func( void ) func左边的void,代表『没有返回值』 func右边的括弧里的voi ...

  8. python学习笔记:第17天 面向对象03 类与类之间的关系

    一.类与类之间的依赖关系 ⼤千世界, 万物之间皆有规则和规律. 我们的类和对象是对⼤千世界中的所有事物进⾏归类. 那事物之间存在着相对应的关系. 类与类之间也同样如此. 在⾯向对象的世界中. 类与类 ...

  9. react--基本用法

    1.安装了babel 但是终端执行 babel src --out-dir build命令时说"babel:command is not found" 经百度,找到solution ...

  10. MDK/Keil 中,J-Link调试查看变量值总是显示<not in scope>

    转载请注明出处,谢谢. MDK/Keil 中,J-Link调试查看变量值总是显示<not in scope> 原因:编译器把代码优化掉了,直接导致在仿真中变量根本没有分配内存,也就无法查看 ...