这题据说是点分治,但是看到有大佬说dus on tree可以写出来,就试了试。。。
https://www.luogu.com.cn/problem/P4149
这个题让我再一次认识了树上启发式合并,谢谢,具体看代码就好
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
const int maxn = 2e5 + 1010;
typedef long long ll;
int k;
map<ll,ll>ins;
int n;
struct Node {
int p;
ll len;
Node(int _p,ll _len):p(_p),len(_len) {}
};
vector<Node>G[maxn];
void add(int be, int en,ll len) {
G[be].push_back(Node(en,len));
}
int siz[maxn];
int son[maxn];
ll dep[maxn];
ll dis[maxn];
int dfs(int x, int fa,ll d,ll dd) {
siz[x] = 1;
dis[x] = dd;
dep[x] = d;
int c = 0;
for (int i=0; i<G[x].size(); i++) {
int p = G[x][i].p;
ll len = G[x][i].len;
if (p == fa) continue;
dfs(p, x,d+1,dd+len);
siz[x] += siz[p];
if (siz[p] > c) {
c = siz[p];
son[x] = p;
}
}
return 0;
}
ll cns = 0;
ll ans;
int cal(int root,int x, int fa) {
ll ln = k+2*dis[root] - dis[x];
if(ins[ln]) {
ans = min(ans,dep[x] + ins[ln] - 2LL*dep[root]);
}
for (int i=0; i<G[x].size(); i++) {
int p = G[x][i].p;
ll len = G[x][i].len;
if (p == fa) continue;
cal(root,p, x);
}
return 0;
}
int cal2(int x, int fa) {
if(ins[dis[x]] == 0){
ins[dis[x]] = dep[x];
}
else{
ins[dis[x]] = min(ins[dis[x]],dep[x]);
}
if(dis[x] == k) {
ans = min(ans,dep[x]-1);
}
for (int i=0; i<G[x].size(); i++) {
int p = G[x][i].p;
ll len = G[x][i].len;
if (p == fa) continue;
cal2(p, x);
}
return 0;
}
int dfs2(int x, int fa, int flag) {
for (int i=0; i<G[x].size(); i++) { //先算轻儿子
int p = G[x][i].p;
ll len = G[x][i].len;
if (p == fa) continue;
if (p == son[x]) continue;
dfs2(p, x, 0);
}
if (son[x] != 0) {//单独算重儿子
dfs2(son[x], x, 1);
}
ll ln = k+dis[x] ;
if(ins[ln]) {
ans = min(ans,dep[x] + ins[ln] - 2LL*dep[x]);
}
if(ins[dis[x]] == 0) ins[dis[x]] = dep[x];
for(int i=0;i<G[x].size();i++){
int p = G[x][i].p;
if(p == fa || p == son[x]) continue;
cal(x,p,x);
cal2(p,x);
}
if (flag == 0) {//删除答案
ins.clear();
}
return 0;
}
int main() {
////
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int be;
scanf("%d %d", &n,&k);
int x,y;
ll len;
ans = 1e17;
for (int i = 2; i <= n; i++) {
scanf("%d %d %lld",&x,&y,&len);
x++,y++;
add(x,y,len);
add(y,x,len);
}
dfs(1, -1,1,0);
dfs2(1, -1, 0);
if(ans == 1e17) ans = -1;
printf("%lld
",ans);
return 0;
}