Codefroces Gym 100781A(树上最长路径)

http://codeforces.com/gym/100781/attachments

题意:有N个点,M条边,问对两两之间的树添加一条边之后,让整棵大树最远的点对之间的距离最近,问这个最近距离是多少。

思路:一开始看成只有两个连通块,后来才注意到是多个连通块。DFS搜树上最长路径。答案有三种:第一种是添加了边之后,树的最长路径还是原来子树的路径,第二种是对子树长度进行排序后,两个最长的距离分别除以2向上取整后加上1。第三种比较难注意到,就是第二第三长的分别除以2向上取整后加上2,因为可能隔着一条边之后比第一种情况更长了。

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <string>
 6 #include <cmath>
 7 #include <queue>
 8 #include <vector>
 9 using namespace std;
10 #define N 100010
11 struct node
12 {
13     int v, nxt;
14 }edge[N*2];
15 int head[N], tot;
16 bool vis[N];
17 int ans[N];
18 int l;
19
20 void add(int u, int v)
21 {
22     edge[tot].v = v; edge[tot].nxt = head[u]; head[u] = tot++;
23 }
24
25 bool cmp(const int &a, const int &b)
26 {
27     return a > b;
28 }
29
30 int dfs(int u)
31 {
32     vis[u] = 1;
33     int m1 = 0, m2 = 0;
34     for(int i = head[u]; ~i; i = edge[i].nxt) {
35         int v = edge[i].v;
36         if(vis[v]) continue;
37         int tmp = dfs(v) + 1;
38         if(tmp > m1) {
39             m2 = m1, m1 = tmp;
40         } else if(tmp > m2) {
41             m2 = tmp;
42         }
43     }
44     if((m1 + m2) > l) l = m1 + m2;
45     return m1;
46 }
47
48 int main()
49 {
50     int n, m;
51     scanf("%d%d", &n, &m);
52     memset(vis, 0, sizeof(vis));
53     memset(head, -1, sizeof(head));
54     memset(ans, 0, sizeof(ans));
55     tot = 0;
56     for(int i = 0; i < m; i++) {
57         int u, v;
58         scanf("%d%d", &u, &v);
59         add(u, v); add(v, u);
60     }
61     int cnt = 0, res = 0;
62     for(int i = 0; i < n; i++) {
63         if(!vis[i]) {
64             l = 0;
65             dfs(i); //搜树上最长路径
66             if(l > res) res = l; //第一种情况
67             ans[cnt++] = l;
68         }
69     }
70     sort(ans, ans + cnt, cmp);
71     if(cnt > 1) res = max(res, (ans[0] + 1) / 2 + (ans[1] + 1) / 2 + 1); //第二种情况
72     if(cnt > 2) res = max(res, (ans[1] + 1) / 2 + (ans[2] + 1) / 2 + 2); //第三种情况
73     printf("%d\n", res);
74     return 0;
75 }
时间: 2024-10-25 04:37:43

Codefroces Gym 100781A(树上最长路径)的相关文章

hdu2196 Computer(树上最长路径 dp)

题目链接:点击打开链接 题意描述:给定一棵树,树上每条边的有一个权值,问从任意一个点出发能走得最长路径是多少? 解题思路:树上最长路径 dp 1.任意找一个点作为根节点,将无根树转化为有根树 2.在dfs过程中更新f[i],g[i],其中f[i]记录以i为节点向下扩展最长路,g[i]为次长路,并用mark标记每个节点最长路的儿子节点 3.在dfs1的过程中更新h[i],h[i]表示以i为节点的向上扩展的最长路 代码: #pragma comment(linker,"/STACK:10240000

树中的最长路径

问题分析: 树中的路径,即是从树上的某个节点起,经过某个转折节点,到达另一个节点这样一条路径.而最长路径就是要找出这些路径中最长的那一条. 算法思路: 对于每个节点,记录下以该节点为根节点的子树中从该节点开始到所有叶子节点的路径中最长的那一条路径长度d1以及次长的那一条路径长度d2(最长和次长两条路径无公共边).那么对于我们想要解决的问题(树中的最长路径),就只需要枚举每个节点作为转折节点,求出所有d1+d2中的最大值. 关于d1,d2的求解: 对于任意一个节点,其d1值等于其所有子节点最大d1

hdu2196 Computer(树的直径||树中的最长路径)

Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5232    Accepted Submission(s): 2640 Problem Description A school bought the first computer some time ago(so this computer's id is 1). D

HDU 2196 Computer (树上最长路)【树形DP】

<题目链接> 题目大意: 输出树上每个点到其它点的最大距离. 解题分析: 下面的做法是将树看成有向图的做法,计算最长路需要考虑几种情况. dp[i][0] : 表示以i为根的子树中的结点与i的最大距离 dp[i][1] : 表示以i为根的子树中的结点与u的次大距离 dp[i][2] : 表示i往父亲节点方向走的最大距离 第一就是点 i 在以点 i 为根的子树中的最长距离,这个可以直接在点 i 的子树中求得: 第二就是点 i 朝父亲节点方向的最长距离,这个距离分为三种: 1) 点 i 在以 fa

014-字串的连接最长路径查找

/* 014-字串的连接最长路径查找 题目描述 给定n个字符串,请对n个字符串按照字典序排列.  输入描述: 输入第一行为一个正整数n(1≤n≤1000),下面n行为n个字符串(字符串长度≤100),字符串中只含有大小写字母. 输出描述: 数据输出n行,输出结果为按照字典序排列的字符串. 输入例子: 9 cap to cat card two too up boat boot 输出例子: boat boot cap card cat to too two up */ //c语言版  #inclu

二叉树中节点的最大距离(树的最长路径)——递归解法

上一篇文章说的是该题的一种变形,并给出了非递归解法. 现在我给出原题的一种递归解法.将会看到,现比较上篇博文,今天给出的递归解法的代码实现是相当简洁的. 问题描述: 如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义"距离"为两节点之间边的个数. 写一个程序,求一棵二叉树中相距最远的两个节点之间的距离.测试用的树: n1 /             \ n2             n3 /        \ n4          n5 /     \    

变形二叉树中节点的最大距离(树的最长路径)——非递归解法

问题描述: 如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义"距离"为两节点之间边的个数. 写一个程序,求一棵二叉树中相距最远的两个节点之间的距离.测试用的树: n1 /             \ n2             n3 /        \ n4          n5 /     \         /   \ n6    n7    n8    n9 /                       / n10                

数据结构:可以用求最短路径的方法思想求最长路径么?给出详细解答。。

数据结构:可以用求最短路径的方法思想求最长路径么?为什么呢? 这里求解最短路径的通用方法有Dijkstra算法和Floyd-Warshall算法,Dijkstra算法不允许边的权值为负,也不允许有回路,而Floyd-Warshall算法可以允许边的权值为负,但不允许负值边构成回路,即可以求解有回路的图 它们都有局限,这两种算法的思想可以用来求最长路径么?? 为什么 不可以? (感谢给我答案的好心人:来自于知乎:http://www.zhihu.com/question/27201255和CSDN

在二进制树中的节点之间的最大距离(最长路径树)——递归解决方案

上一篇文章即是对这一主题的变化.并给出了一个非递归溶液. 我给出原题的一种递归解法. 将会看到,现比較上篇博文.今天给出的递归解法的代码实现是相当简洁的. 问题描写叙述: 假设我们把二叉树看成一个图.父子节点之间的连线看成是双向的,我们姑且定义"距离"为两节点之间边的个数. 写一个程序.求一棵二叉树中相距最远的两个节点之间的距离.測试用的树: n1 /             \ n2             n3 /        \ n4          n5 /     \