求树的直径,然后保存直径的端点,然后枚举路径上的点
//By AcerMo #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int inf=99999999; int dis[1001][1001]; int fr[1001],to[1001]; int m,n,cnt; int maxn=0; inline int read() { int x=0;char ch=getchar(); while (ch>'9'||ch<'0') ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x; } inline void floyd() { for (int k=1;k<=n;k++) for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]); return ; } inline void getdia() { for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if(dis[i][j]!=inf) maxn=max(maxn,dis[i][j]); for (int i=1;i<=n;i++) for (int k=1;k<=n;k++) if(maxn==dis[i][k]) fr[++cnt]=i,to[cnt]=k; return ; } inline void simul() { int minn=inf; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) { int ans=0; for (int l=1;l<=cnt;l++) if(dis[i][j]!=inf&&dis[i][j]<=m&&dis[fr[l]][i]+dis[i][j]+dis[j][to[l]]==maxn) { for (int k=1;k<=n;k++) { if(k!=i&&k!=j) ans=max(ans,(dis[k][i]+dis[k][j]-dis[i][j])/2); } minn=min(minn,ans); } } return (void)(cout<<minn); } int main() { n=read();m=read(); for (int i=1;i<=n;i++) for (int k=1;k<=n;k++) if (i!=k) dis[i][k]=inf; else dis[i][k]=0; for (int i=1;i<n;i++) { int a=read(),b=read(),c=read(); dis[a][b]=c;dis[b][a]=c; } floyd();getdia();simul(); return 0; }