1073. 树的中心
题目链接
1073. 树的中心
给定一棵树,树中包含 \(n\) 个结点(编号\(1~n\))和 \(n−1\) 条无向边,每条边都有一个权值。
请你在树中找到一个点,使得该点到树中其他结点的最远距离最近。
输入格式
第一行包含整数 \(n\)。
接下来 \(n−1\) 行,每行包含三个整数 \(a_i,b_i,c_i\),表示点 \(a_i\) 和 \(b_i\) 之间存在一条权值为 \(c_i\) 的边。
输出格式
输出一个整数,表示所求点到树中其他结点的最远距离。
数据范围
\(1≤n≤10000,\)
\(1≤a_i,b_i≤n,\)
\(1≤c_i≤10^5\)
输入样例:
5
2 1 1
3 2 1
4 3 1
5 1 1
输出样例:
2
解题思路
换根dp,dfs
对于一个节点来说其最长距离要么向上要么向下,对于向下好分析,向上不能经过当前节点,可以统计向下的最长距离和次长距离,以及对于一个节点来说向下最长时其指向的子节点,接着继续分析向上的情况,如果其父节点的最长指向的节点正好是自己,则用次长路径更新父节点否则用最长路径(部分代码段):
if(p[x]!=y)u[y]=max(u[x],d1[x])+w;
else
u[y]=max(u[x],d2[x])+w;
- 时间复杂度:\(O(n)\)
代码
// Problem: 树的中心
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/1075/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=10005,inf=0x3f3f3f3f;
int n,d1[N],d2[N],u[N],p[N];
vector<PII> adj[N];
bool is_leaf[N];
int dfs_d(int x,int fa)
{
d1[x]=d2[x]=-inf;
for(auto t:adj[x])
{
int y=t.fi,w=t.se;
if(y==fa)continue;
int d=dfs_d(y,x)+w;
if(d>=d1[x])
{
d2[x]=d1[x];
d1[x]=d;
p[x]=y;
}
else if(d>d2[x])d2[x]=d;
}
if(d1[x]==-inf)
{
is_leaf[x]=true;
d1[x]=d2[x]=0;
}
return d1[x];
}
void dfs_u(int x,int fa)
{
for(auto t:adj[x])
{
int y=t.fi,w=t.se;
if(y==fa)continue;
if(p[x]!=y)u[y]=max(u[x],d1[x])+w;
else
u[y]=max(u[x],d2[x])+w;
dfs_u(y,x);
}
}
int main()
{
cin>>n;
for(int i=1;i<n;i++)
{
int a,b,c;
cin>>a>>b>>c;
adj[a].pb({b,c});
adj[b].pb({a,c});
}
dfs_d(1,-1);
dfs_u(1,-1);
int res=inf;
for(int i=1;i<=n;i++)
if(is_leaf[i])res=min(res,u[i]);
else
res=min(res,max(d1[i],u[i]));
cout<<res;
return 0;
}