poj:1985:Cow Marathon(求树的直径)

Cow Marathon

Time Limit: 2000MS   Memory Limit: 30000K
Total Submissions: 5496   Accepted: 2685
Case Time Limit: 1000MS

Description

After hearing about the epidemic of obesity in the USA, Farmer John wants his cows to get more exercise, so he has committed to create a bovine marathon for his cows to run. The marathon route will include a pair of farms and a path comprised of a sequence of roads between them. Since FJ wants the cows to get as much exercise as possible he wants to find the two farms on his map that are the farthest apart from each other (distance being measured in terms of total length of road on the path between the two farms). Help him determine the distances between this farthest pair of farms.

Input

* Lines 1.....: Same input format as "Navigation Nightmare".

Output

* Line 1: An integer giving the distance between the farthest pair of farms.

Sample Input

7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S

Sample Output

52

Hint

The longest marathon runs from farm 2 via roads 4, 1, 6 and 3 to farm 5 and is of length 20+3+13+9+7=52.

分析

求树的直径,可以两遍bfs,求树的直径。

我做的是树形dp。

随便找一个节点把无根树变为有根树,考虑随便找一个根,得到一棵有根树。那么每条路径都有一个根。

然后计算其他子节点作根的最长路径。dp[u]表示以u为根的子树中离根的最远距离。则dp[u]=max(dp[v])+1;以u为根的最长路径即为所有u的孩子中,最大的dp值+次大的dp值+1。

code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4
 5 using namespace std;
 6
 7 const int MAXN = 50010;
 8 struct Edge{
 9     int to,nxt,w;
10 }e[500100];
11 int head[MAXN],dp[MAXN];
12 bool vis[MAXN];
13 int n,m,tot,ans;
14 char s[5];
15
16 inline void init()
17 {
18     memset(vis,false,sizeof(vis));
19     memset(dp,0,sizeof(dp));
20     memset(head,0,sizeof(head));
21     tot = 0;
22     ans = 0;
23 }
24 inline void add_edge(int u,int v,int w)
25 {
26     e[++tot].to = v;e[tot].w = w;e[tot].nxt = head[u];
27     head[u] = tot;
28     e[++tot].to = u;e[tot].w = w;e[tot].nxt = head[v];
29     head[v] = tot;
30 }
31 void dfs(int u)
32 {
33     vis[u] = true;
34     for (int i=head[u]; i; i=e[i].nxt)
35     {
36         int v = e[i].to,w = e[i].w;
37         if (!vis[v])
38         {
39             dfs(v);
40             ans = max(ans,dp[u]+w+dp[v]);
41             dp[u] = max(dp[u],dp[v]+w);
42         }
43     }
44 }
45 int main()
46 {
47     while (~scanf("%d%d",&n,&m))
48     {
49         init();
50         for (int x,y,z,i=1; i<=m; ++i)
51         {
52             scanf("%d%d%d%s",&x,&y,&z,s);
53             add_edge(x,y,z);
54         }
55         dfs(1);
56         printf("%d\n",ans);
57     }
58     return 0;
59 }
时间: 2024-10-14 00:22:43

poj:1985:Cow Marathon(求树的直径)的相关文章

poj 1985 Cow Marathon 【树的直径】

题目:poj 1985 Cow Marathon 题意:给出一个树,让你求树的直径. 分析: 树的直径:树上两点之间的最大距离. 我们从任意一点出发,BFS一个最远距离,然后从这个点出发,在BFS一个最远距离,就是树的直径. AC代码: /* POJ:1985 Cow Marathon 2014/10/12/21:18 Yougth*/ #include <cstdio> #include <iostream> #include <algorithm> #include

POJ 1985 Cow Marathon【树的直径】

题目大意:给你一棵树,要你求树的直径的长度 思路:随便找个点bfs出最长的点,那个点一定是一条直径的起点,再从那个点BFS出最长点即可 以下研究了半天才敢交,1.这题的输入格式遵照poj1984,其实就是把后面的字母无视即可 2.这题数据量没给,所以把数组开得很大才敢交TUT #include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <

poj 1985 Cow Marathon

题目连接 http://poj.org/problem?id=1985 Cow Marathon Description After hearing about the epidemic of obesity in the USA, Farmer John wants his cows to get more exercise, so he has committed to create a bovine marathon for his cows to run. The marathon ro

Cow Marathon(树的直径)

传送门 Cow Marathon Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 5362   Accepted: 2634 Case Time Limit: 1000MS Description After hearing about the epidemic of obesity in the USA, Farmer John wants his cows to get more exercise, so he has

POJ 1985 Cow Marathon(树的直径)

http://poj.org/problem?id=1985 题意: 有一个树结构, 给你树的全部边(u,v,cost), 表示u和v两点间有一条距离为cost的边. 然后问你该树上最远的两个点的距离是多少?(即树的直径) 分析: 对于树的直径问题, <<算法导论>>(22 2-7)例题有说明. 详细解法: 首先从树上随意一个点a出发, (BFS)找出到这个点距离最远的点b. 然后在从b点出发(BFS)找到距离b点最远的点c. 那么bc间的距离就是树的直径. 证明: 1.    a

BZOJ 3363 POJ 1985 Cow Marathon 树的直径

题目大意:给出一棵树.求两点间的最长距离. 思路:裸地树的直径.两次BFS,第一次随便找一个点宽搜.然后用上次宽搜时最远的点在宽搜.得到的最长距离就是树的直径. CODE: #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 80010 using namespace std; int

POJ 1985 Cow Marathon (树形DP,树的直径)

题意:给定一棵树,然后让你找出它的直径,也就是两点中的最远距离. 析:很明显这是一个树上DP,应该有三种方式,分别是两次DFS,两次BFS,和一次DFS,我只写了后两种. 代码如下: 两次BFS: #include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; const int max

poj2631 求树的直径裸题

题目链接:http://poj.org/problem?id=2631 题意:给出一棵树的两边结点以及权重,就这条路上的最长路. 思路:求实求树的直径. 这里给出树的直径的证明: 主要是利用了反证法: 假设 s-t这条路径为树的直径,或者称为树上的最长路 现有结论,从任意一点u出发搜到的最远的点一定是s.t中的一点,然后在从这个最远点开始搜,就可以搜到另一个最长路的端点,即用两遍广搜就可以找出树的最长路 证明: 1.设u为s-t路径上的一点,结论显然成立,否则设搜到的最远点为T则   dis(u

hdu4612 无向图中任意添加一条边后使桥的数量最少 / 无向图缩点+求树的直径

题意如上,含有重边(重边的话,俩个点就可以构成了边双连通). 先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少.这里学习了树的直径求法:第一次选任意起点U,进行bfs,到达最远的一个点v(level最深)该点必然是树的直径的一个端点,,再从该点出发,bfs,到最深的一点,该点深度就是直径.(证明:先假设u,是直径上一点,S,T是直径的端点,设v!=t,则有(V,U)+(U,S)>(T,U)+(U,S),矛盾,故t=v:若u不是直径上一点,设u到直径上的一点为x,同理易证. 最后 缩