【链接】
bzoj1999
【题目大意】
好像是加强版啊
这里博主就补个图吧。
【解题报告】
Dfs大法好啊
其实这题要仔细思考,思路清晰后就可以得到两个结论。
(1)对于树中的任意一点,距离其最远的点一定是树的直径的某一端点。
(2)所有的直径是等价的,即任意一条所能求出的该最小偏心距相等。
所以先求一遍最长链。
然后先求链中的最小偏心距,最小偏心距的路径肯定是经过核心的(除非是一个点)。
然后因为最小偏心距可能受其他直径影响,所以再求一遍路径到其他点中的最大距离,挑小的,就行了。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=500005,maxm=1000005,INF=((1<<30)-1)+1;
int n,S,tot,ans,L,R,fa[maxn],dst[maxn],lnk[maxn],w[maxm],son[maxm],nxt[maxm];
bool vis[maxn];
inline char nc()
{
static char buf[100000],*l,*r;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
if (l==r) return EOF; return *l++;
}
inline int Read()
{
int res=0; char ch=nc();
while (ch<'0'||ch>'9') ch=nc();
while (ch>='0'&&ch<='9') res=res*10+ch-48,ch=nc();
return res;
}
void Add(int x,int y,int z) {w[++tot]=z; son[tot]=y; nxt[tot]=lnk[x]; lnk[x]=tot;}
void Dfs(int x,int Fa)
{
fa[x]=Fa;
for (int j=lnk[x]; j; j=nxt[j])
if (son[j]!=Fa&&!vis[son[j]]) dst[son[j]]=dst[x]+w[j],Dfs(son[j],x);
}
void Getline()
{
memset(dst,0,sizeof(dst));
Dfs(1,0); R=0;
for (int i=1; i<=n; i++)
if (dst[i]>dst[R]) R=i;
memset(dst,0,sizeof(dst));
Dfs(R,0); L=0;
for (int i=1; i<=n; i++)
if (dst[i]>dst[L]) L=i;
}
void Solve()
{
int i=L,j=L; ans=INF;
for (; i; i=fa[i])
{
while (fa[j]&&dst[i]-dst[fa[j]]<=S) j=fa[j];
ans=min(ans,max(dst[j],dst[L]-dst[i]));
}
for (i=L; i; i=fa[i]) vis[i]=1;
for (i=L; i; i=fa[i]) dst[i]=0,Dfs(i,fa[i]);
for (int i=1; i<=n; i++) ans=max(ans,dst[i]);
printf("%d\n",ans);
}
int main()
{
freopen("1999.in","r",stdin);
freopen("1999.out","w",stdout);
n=Read(); S=Read(); tot=0;
memset(lnk,0,sizeof(lnk));
for (int i=1,x,y,z; i<n; i++) x=Read(),y=Read(),z=Read(),Add(x,y,z),Add(y,x,z);
Getline();
Solve();
return 0;
}