lgswdn_SA
2020-05-08 13:16:11
由于可以
之后,我们要看加哪条边。显然,我们要连接两个树的“交通枢纽”然后连接。“交通枢纽”指树上到这棵树上到其他点的最远距离 最小的一个点。显然在求出最远距离后,这个也可以通过枚举求出。假设两个交通枢纽
于是这个结果就是第一棵树的直径,第二棵树的直径和重新连边后的直径的最大值。
#include<bits/stdc++.h>
using namespace std;
const int N=5e3+9;
struct edge{int to,nxt,w;}e[N*2]; int hd[N],tot;
void add(int u,int v,int w){e[++tot]=(edge){v,hd[u],w};hd[u]=tot;}
int f[N][2],mx[N],g[N],tmp[2],mn[2],ans=1e9;
//f为子树里面最远的点(f[u][0]代表最远,f[u][1]代表次远),g为子树外最远的点(后面通过和f取max算出总的最远的点)
//mx记录最远的那个点是从哪个儿子节点出发的,便于后面计算g
void dfs1(int u,int fa){
for(int i=hd[u],v;i;i=e[i].nxt)
if((v=e[i].to)!=fa){
dfs1(v,u);
if(f[v][0]+e[i].w>f[u][0]){
f[u][1]=f[u][0],f[u][0]=f[v][0]+e[i].w,mx[u]=v;
}
else if(f[v][0]+e[i].w>f[u][1]) f[u][1]=f[v][0]+e[i].w;
}
}
void dfs2(int u,int fa,int k){
for(int i=hd[u],v;i;i=e[i].nxt)
if((v=e[i].to)!=fa){
if(mx[u]!=v) g[v]=max(g[u]+e[i].w,f[u][0]+e[i].w);
else g[v]=max(g[u]+e[i].w,f[u][1]+e[i].w);
dfs2(v,u,k);
}
g[u]=max(g[u],f[u][0]);
tmp[k]=max(tmp[k],g[u]);
mn[k]=min(mn[k],g[u]);
}
int main(){
int n; scanf("%d",&n);
for(int i=1,u,v,w;i<n;i++)
scanf("%d%d%d",&u,&v,&w),add(u,v,w),add(v,u,w);
for(int u=1;u<=n;u++){
for(int i=hd[u],v;i;i=e[i].nxt){
if((v=e[i].to)<=u) continue;
memset(f,0,sizeof(f)),memset(g,0,sizeof(g)),memset(mx,0,sizeof(mx));
tmp[0]=tmp[1]=0,mn[0]=mn[1]=1e9;
//上面是初始化
dfs1(u,v),dfs2(u,v,0),dfs1(v,u),dfs2(v,u,1);
ans=min(ans,max(max(tmp[0],tmp[1]),e[i].w+mn[0]+mn[1]));
//更新答案
}
}
printf("%d",ans);
return 0;
}