SSLOJ 1248.B
程序员文章站
2022-05-12 15:07:51
...
题目:
分析:
经典的点分治(虽然我一开始也不会)
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#include<deque>
#include<set>
#define N 101000
#define LL long long
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
LL n,S,E,last[N],next[N*10],to[N*10],root,size[N],mx[N],bz[N],tot=0,nn;
LL ans=214748347474447747ll,deep[N],date[N*10];
struct node{
LL x;LL y;
}a[N];
//建边
void putin(LL x,LL y,LL z) {next[++tot]=last[x];last[x]=tot;to[tot]=y;date[tot]=z;return;}
//求出树的重心
void findroot(LL x,LL fa)
{
size[x]=1;
for(LL i=last[x];i;i=next[i])
{
if(to[i]==fa||bz[to[i]]) continue;
findroot(to[i],x);
size[x]+=size[to[i]];
mx[x]=max(size[to[i]],mx[x]);
}
mx[x]=max(mx[x],nn-size[x]);
if(mx[x]<mx[root]) root=x;
}
//找出深度
void getdeep(LL x,LL fa,LL jy)
{
for(LL i=last[x];i;i=next[i])
{
LL y=to[i];
if(bz[y]||y==fa) continue;
deep[y]=deep[x]+date[i];
if(jy==0) getdeep(y,x,y);
else getdeep(y,x,jy);
}
a[++tot].x=deep[x];a[tot].y=jy;
}
bool cnt(node x,node y){return x.x<y.x;}
void calc()
{
sort(a+1,a+tot+1,cnt);
LL i=1,j=tot;
while(i<j)
{
LL k=a[i].x+a[j].x-2;
if(a[i].y==a[j].y)
{
if(a[i].x+a[j-1].x-2<S) i++;
else j--;
}
else
{
if(k>=S)
{
ans=min(ans,k);
j--;
}
else i++;
}
}
}
void dg(LL x,LL fa)
{
bz[x]=1;tot=0;deep[x]=1;getdeep(x,fa,0);
calc();
for(LL i=last[x];i;i=next[i])
{
LL y=to[i];if(bz[y]||y==fa) continue;
root=0;nn=size[y];
findroot(y,x);dg(y,x);
}
}
int main()
{
n=read();S=read();E=read();
for(LL i=1;i<n;i++)
{
LL x=read(),y=read(),z=read();
putin(x,y,z);putin(y,x,z);
}
root=0;mx[0]=2147483647;
nn=n;findroot(1,0);
dg(root,0);
ans=ans>E?-1:ans;
printf("%lld",ans);
return 0;
}