传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2599
我不知道我的点分治是怎么写的……
50s+倒数第一 = = 、
毕竟还是过了233
那就每次挑点分治
计算经过这个点的ans
维护一个点到根的和和距离
枚举子树中的点,计算它与其他子树中sum[i]+sum[j]=k且dep最小
set搞搞
好像是nlog^2n??
然后莫名T成翔
Code:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;
const int maxn=200005;
struct edge{int u,v,w;};
vector<edge>G[maxn];
typedef long long LL;
typedef pair<LL,int> pli;
int n,root,All;
int dsize,siz[maxn],f[maxn],dep[maxn],ans=maxn+233;
LL sum[maxn],k;
bool cant[maxn];
set<pli>S;
set<pli>::iterator it;
pli data[maxn];
void makert(int u,int fa){
siz[u]=1;f[u]=0;
for(int i=0;i<G[u].size();i++){
edge e=G[u][i];
if(e.v==fa||cant[e.v])continue;
makert(e.v,u);
siz[u]+=siz[e.v];
f[u]=max(f[u],siz[e.v]);
}f[u]=max(f[u],All-siz[u]);
if(f[root]>f[u])root=u;
}
void dfs(int u,int fa){
data[++dsize]=pli(sum[u],dep[u]);
for(int i=0;i<G[u].size();i++){
edge e=G[u][i];
if(cant[e.v]||e.v==fa)continue;
sum[e.v]=sum[u]+e.w;dep[e.v]=dep[u]+1;
dfs(e.v,u);
}
}
void calc(int u){
S.clear();dep[u]=0;sum[u]=0;
S.insert(pli(0,0));
for(int i=0;i<G[u].size();i++){
edge e=G[u][i];
if(cant[e.v])continue;
dsize=0;
sum[e.v]=e.w;
dep[e.v]=1;
dfs(e.v,u);
for(int j=1;j<=dsize;j++){
it=S.lower_bound(pli(k-data[j].first,0));
if(it==S.end()||it->first+data[j].first!=k)continue;
ans=min(ans,data[j].second+it->second);
}
for(int j=1;j<=dsize;j++)S.insert(data[j]);
}
}
void solve(int u){
calc(u);cant[u]=1;
for(int i=0;i<G[u].size();i++){
edge e=G[u][i];if(cant[e.v])continue;
f[root=0]=n+1;
makert(e.v,0);
All=siz[e.v];
solve(root);
}
}
int main(){
scanf("%d",&n);All=n;cin>>k;
for(int i=1;i<n;i++){
int u,v,w;scanf("%d%d%d",&u,&v,&w);u++;v++;
G[u].push_back((edge){u,v,w});
G[v].push_back((edge){v,u,w});
}f[root=0]=n+1;
makert(1,0);
solve(root);
if(ans==maxn+233)puts("-1");
else cout<<ans<<endl;
return 0;
}