这题据说是点分治,但是看到有大佬说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; }