树的直径就是这棵树上存在的最长路径。 求法: 两次dfs或bfs
一. 从任意一点开始,搜索到这个点最长的距离,记录下搜到的点。
假设此树的最长路径是从s到t,我们选择的点为u。反证法:假设搜到的点是v。
1、v在这条最长路径上,那么dis[u,v]>dis[u,v]+dis[v,s],显然矛盾。
2、v不在这条最长路径上,我们在最长路径上选择一个点为po,则dis[u,v]>dis[u,po]+dis[po,t],那么有dis[s,v]=dis[s,po]+dis[po,u]+dis[u,v]>dis[s,po]+dis[po,t]=dis[s,t],即dis[s,v]>dis[s,t],矛盾。
也许你想说u本身就在最长路径,或则其它的一些情况,但其实都能用类似于上面的反证法来证明的。
综上所述,你两次dfs(bfs)就可以求出最长路径的两个端点和路径长度。
二. 在第一次搜索基础上,从记录下的点开始,求到此点的最远距离,就可以求出树上存在的最长路径。
桃花一簇开无主,可爱深红映浅红。
——《题百叶桃花》
桃花长在桃树上,树的每个节点有一个桃花,调皮的HtBest想摘尽可能多的桃花。HtBest有一个魔法棒,摘到树上任意一条链上的所有桃花,由于HtBest法力有限,只能使用一次魔法棒,请求出Htbest最多可以摘到多少个桃花。
输入描述:
第一行有一个正整数n,表示桃树的节点个数。
接下来n-1行,第i行两个正整数ai,bi ,表示桃树上的节点ai,bi之间有一条边。
输出描述:
第一行一个整数,表示HtBest使用一次魔法棒最多可以摘到多少桃花。
示例1
输入
复制
3
1 2
2 3
输出
复制
3
示例2
输入
复制
3
1 2
1 3
输出
复制
3
示例3
输入
复制
4
1 2
2 3
3 4
输出
复制
4
备注:
对于100%的测试数据:
1 ≤ n ≤ 1000000
数据量较大,注意使用更快的输入输出方式。
代码:
#include<iostream> #include<cstring> #include<vector> #include<queue> using namespace std; #define ll long long #define maxn 1000005 vector<int> v[maxn]; int id=0, mx=1; int bo[maxn]; void dfs(int a,int b) { bo[a]=b; if(b>mx) { id=a; mx=b; } for(int i=0;i<v[a].size() ;i++) { int to=v[a][i]; if(bo[to]==0) { dfs(to,b+1); } } } int main() { int n; scanf("%d",&n); n-=1; int a,b; while(n--) { scanf("%d%d",&a,&b); v[a].push_back(b); v[b].push_back(a); } dfs(1,1); mx=1; memset(bo,0,sizeof(bo)); dfs(id,1); printf("%d\n",mx); return 0; }