

易错点:
- 求树的直径的端点时,在获取最深的点时应当使用">="符号.
- 求树的直径时需要附带vis[i]数组以保证每个点仅访问一次(源点dis为0).
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#define ll long long
using namespace std;
const int MAXN=3e5,MAXM=MAXN*2;
struct Edge{
int from,to,nxt;
ll w;
}e[MAXM];
int head[MAXN],edgeCnt=1;
void addEdge(int u,int v,ll w){
e[++edgeCnt].from=u;
e[edgeCnt].to=v;
e[edgeCnt].w=w;
e[edgeCnt].nxt=head[u];
head[u]=edgeCnt;
}
ll dep[MAXN];
bool vis[MAXN];
int n;
ll length;//树的直径
int bfs(int s){//返回深度最大的点
memset(dep,0,sizeof(dep));
memset(vis,0,sizeof(vis));
queue<int> q;
q.push(s);
vis[s]=1;
while(!q.empty()){
int nowU=q.front();
q.pop();
for(int i=head[nowU];i;i=e[i].nxt){
int nowV=e[i].to;
if(!vis[nowV]){
dep[nowV]=dep[nowU]+e[i].w;
vis[nowV]=1;
q.push(nowV);
}
}
}
int ans=0;
for(int i=1;i<=n;i++)
if(dep[ans]<=dep[i]){//注意( "=" )
ans=i;
length=dep[i];
}
return ans;
}
ll dis1[MAXN];
void dfs1(int x,int in_edge){
for(int i=head[x];i;i=e[i].nxt){
if(i==(in_edge^1))continue;
int nowV=e[i].to;
dis1[nowV]=dis1[x]+e[i].w;
dfs1(nowV,i);
}
}
ll dis2[MAXN];
void dfs2(int x,int in_edge){
for(int i=head[x];i;i=e[i].nxt){
if(i==(in_edge^1))continue;
int nowV=e[i].to;
dis2[nowV]=dis2[x]+e[i].w;
dfs2(nowV,i);
}
}
int main(){
int m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;
ll w;
cin>>u>>v>>w;
addEdge(u,v,w);
addEdge(v,u,w);
}
int st=bfs(1);
int ed=bfs(st);//树上直径的两端点
dfs1(st,0);
dfs2(ed,0);
ll ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,min(dis1[i],dis2[i]));//最坏情况下
ans=ans+length;
cout<<ans<<endl;
return 0;
}