思路:找出树上的直径端点,然后枚举树上的其他点,答案取最大值。(弱弱我一开始找直径中点,然后dfs求除直径外距离中点的最长链统计答案,不知道为什么错了捏)
/**********
明天你是否会想起
昨天未调完的题
明天你是否还惦记
考场写挂的暴力
**********/
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e18;//按题目要求随时修改.
void read(int &x){
int f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while(s<='9'&&s>='0'){x=x*10%mod+(s-'0')%mod;s=getchar();}//改成了取模~~
x=x%mod*f;//改成了取模~
}
typedef pair<int,int>PII;
const int N=2e5+10;
vector<PII>f[N];
int l_t,r_t;
bool str[N];
int sum[N],fa[N],dep[N],son[N],top[N];
void dfs(int father,int cur)
{
for(auto [v,len]:f[cur])
{
if(v==father) continue;
dep[v]=dep[cur]+len;
if(dep[v]>dep[l_t]) l_t=v;
dfs(cur,v);
}
}
int ans_2;
void dfs_1(int father,int cur)
{
sum[cur]=1;
for(auto [v,len]:f[cur])
{
if(v==father) continue;
dep[v]=dep[cur]+len;
fa[v]=cur;
dfs_1(cur,v);
sum[cur]+=sum[v];
if(sum[v]>sum[son[cur]]) son[cur]=v;
}
}
void dfs_2(int fcur,int cur)
{
top[cur]=fcur;
if(son[cur]) dfs_2(fcur,son[cur]);
for(auto [v,len]:f[cur])
{
if(v==fa[cur]||v==son[cur]) continue;
dfs_2(v,v);
}
}
int lca(int l,int r)
{
while(top[l]!=top[r])
{
if(dep[top[l]]>dep[top[r]]) l=fa[top[l]];
else r=fa[top[r]];
}
return dep[l]<dep[r]?l:r;
}
int dis(int a,int b){return dep[a]+dep[b]-2*dep[lca(a,b)];}
void solve()
{
int n,m;
cin>>n>>m;
while(m--)
{
int u,v,len;
cin>>u>>v>>len;
f[u].push_back({v,len});
f[v].push_back({u,len});
}
dfs(0,1);
r_t=l_t;
dep[l_t]=0;
dfs(0,l_t);
swap(l_t,r_t);//俩遍dfs求树的俩个端点
dfs_1(0,l_t);
dfs_2(l_t,l_t);//树剖,用来求lca,lca用来求树上俩点之间的距离
//l_t是直径的一个端点,也是树根,r_t是树上直径的另一个端点
int ans=0;
for(int i=1;i<=n;i++)
{
if(i==l_t||i==r_t) continue;
ans=max(ans,min(dis(i,l_t),dis(i,r_t))+dep[r_t]);//计算答案然后取最大
}
cout<<ans<<'\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int t;
t=1;
while(t--){solve();}
return 0;
}