[模板]树的最长路径
题目描述
给定一棵树,树中包含 n 个结点(编号1~n)和 n-1 条无向边,每条边都有一个权值。
现在请你找到树中的一条最长路径。
换句话说,要找到一条路径,使得使得路径两端的点的距离最远。
注意:路径中可以只包含一个点。
输入格式
第一行包含整数 n。
接下来 n-1 行,每行包含三个整数 ai,bi,ci,表示点 ai 和 bi 之间存在一条权值为 ci 的边。
输出格式
输出一个整数,表示树的最长路径的长度。
样例输入1
6
5 1 6
1 4 5
6 3 9
2 6 8
6 1 7
样例输出1
22
注释说明
1≤n≤10000,1≤ai,bi≤n,-10^5≤ci≤10^5
#include <bits/stdc++.h>
using namespace std;
int n,f[100005],ww,maxn,maxf;
bool used[100002];
struct ed{int to,wi;
};
vector<ed>a[200002];
void dfs(int x,int fa){for(int i=0;i<a[x].size();i++){int v=a[x][i].to;if(v==fa)continue;f[v]=a[x][i].wi+f[x];dfs(v,x);}if(maxn<f[x]){maxn=f[x];maxf=x;}
}
int main(){scanf("%d",&n);for(int i=1;i<n;i++){int v,u;scanf("%d%d%d",&v,&u,&ww);a[v].push_back({u,ww});a[u].push_back({v,ww});}dfs(1,-1);f[maxf]=0;//memset(f,0,sizeof(f));maxn=0;dfs(maxf,-1);printf("%d\n",maxn);}
/*
6
5 1 6
1 4 5
6 3 9
2 6 8
6 1 7
*/
解法一:从任意一点u出发搜到的最远的点一定是s、t中的一点,然后在从这个最远点开始搜,就可以搜到另一个最长路的端点,即用两遍广搜就可以找出树的最长路。
解法二:算是树的直径的一个性质,树的直径的长度一定会是某个点的最长距离f1[x]与次长距离f2[x]之和。最后求出max{f1[x]+f2[x]}就可以了。
————————————————版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/linzhi6236/article/details/131604008
#include <bits/stdc++.h>
using namespace std;
int n,f1[100005],f2[100005],ww,ans;
struct ed{int to,wi;
};
vector<ed>a[200002];
void dfs(int x,int fa){f1[x]=0;f2[x]=0;for(int i=0;i<a[x].size();i++){int v=a[x][i].to;if(v==fa)continue; dfs(v,x);if(f1[v]+a[x][i].wi>f1[x]){f2[x]=f1[x];f1[x]=f1[v]+a[x][i].wi;}else if(f1[v]+a[x][i].wi>f2[x]){f2[x]=f1[v]+a[x][i].wi;}}ans=max(ans,f1[x]+f2[x]);
}
int main(){scanf("%d",&n);for(int i=1;i<n;i++){int v,u;scanf("%d%d%d",&v,&u,&ww);a[v].push_back((ed){u,ww});a[u].push_back((ed){v,ww});}dfs(1,-1);printf("%d\n",ans);}
/*
6
5 1 6
1 4 5
6 3 9
2 6 8
6 1 7
*/