SPOJ1825:Free tour II
2018-02-26 19:05
411 查看
题意
luogu的翻译给定一棵n个点的树,树上有m个黑点,求出一条路径,使得这条路径经过的黑点数小于等于k,且路径长度最大
Sol
点分治辣如果是等于\(k\)的话,开个桶取\(max\)就好了
而小于等于\(k\),就可以把桶换成树状数组,求前缀\(max\)
很慢能过
# include <bits/stdc++.h> # define RG register # define IL inline # define Fill(a, b) memset(a, b, sizeof(a)) using namespace std; typedef long long ll; const int _(2e5 + 5); IL int Input(){ RG int x = 0, z = 1; RG char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1; for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48); return x * z; } int n, m, k, mx[_], root, size[_], vis[_], tot, first[_], cnt; struct Edge{ int to, w, next; } edge[_ << 1]; int ans, black[_], pass[_], dis[_], t[_], S[_], tk, G[_]; IL void Add(RG int u, RG int v, RG int w){ edge[cnt] = (Edge){v, w, first[u]}, first[u] = cnt++; } IL void GetRoot(RG int u, RG int ff){ size[u] = 1, mx[u] = 0; for(RG int e = first[u]; e != -1; e = edge[e].next){ RG int v = edge[e].to; if(vis[v] || v == ff) continue; GetRoot(v, u); size[u] += size[v]; mx[u] = max(mx[u], size[v]); } mx[u] = max(mx[u], tot - size[u]); if(mx[u] < mx[root]) root = u; } IL void GetDeep(RG int u, RG int ff, RG int dd, RG int pp){ if((pp += black[u]) > tk) return; pass[u] = pp, dis[u] = dd, S[++S[0]] = u, G[++G[0]] = u; for(RG int e = first[u]; e != -1; e = edge[e].next){ RG int v = edge[e].to, w = edge[e].w; if(vis[v] || v == ff) continue; GetDeep(v, u, dd + w, pp); } } IL void Cls(RG int x){ if(!x) t[x] = 0; for(; x && x <= m; x += x & -x) t[x] = 0; } IL void Modify(RG int x, RG int v){ if(!x) t[x] = max(t[x], v); for(; x && x <= m; x += x & -x) t[x] = max(t[x], v); } IL int Query(RG int x){ RG int ret = t[0]; for(; x; x -= x & -x) ret = max(ret, t[x]); return ret; } IL void Calc(RG int u){ for(RG int e = first[u]; e != -1; e = edge[e].next){ RG int v = edge[e].to, w = edge[e].w; if(vis[v]) continue; GetDeep(v, u, w, 0); for(RG int i = 1; i <= S[0]; ++i){ RG int dd = dis[S[i]], pp = tk - pass[S[i]], tt = Query(pp); ans = max(ans, dd + tt); } for(; S[0]; --S[0]){ RG int dd = dis[S[S[0]]], pp = pass[S[S[0]]]; Modify(pp, dd); } } for(; G[0]; --G[0]) Cls(pass[G[G[0]]]); } IL void Solve(RG int u){ vis[u] = 1, tk = k - black[u]; if(tk >= 0) Calc(u); for(RG int e = first[u]; e != -1; e = edge[e].next){ RG int v = edge[e].to; if(vis[v]) continue; root = 0, tot = size[v]; GetRoot(v, u), Solve(root); } } int main(RG int argc, RG char* argv[]){ tot = n = Input(), k = Input(), m = Input(); Fill(first, -1), ans = 0; for(RG int i = 1; i <= m; ++i) black[Input()] = 1; for(RG int i = 1; i < n; ++i){ RG int u = Input(), v = Input(), w = Input(); Add(u, v, w), Add(v, u, w); } mx[0] = n + 1, GetRoot(1, 0), Solve(root); printf("%d\n", ans); return 0; }
相关文章推荐
- spoj 1825 Free tour II(树分治+启发式合并)
- spoj 1825 Free tour II(树的点分治)
- 【SPOJ1825】Free Tour II-点分治+桶排序
- spoj 1825 Free tour II 点分治
- SPOJ 1825 Free tour II
- SPOJ 1825 Free tour II 树分治
- SPOJ 1825 Free tour II 解题报告(树分治)
- SPOJ 1825 Free tour II
- 【SPOJ】1825 Free tour II 点分治
- SPOJ1825:Free tour II
- 树分治点分治(spoj1825 Free tour II)
- Spoj - 1825 Free tour II(树的点分治)
- 【SPOJ1825】Free tour II (点分治,启发式)
- spoj1825 Free tour II 点分治
- spoj1825 Free tour II(点分治)
- SPOJ 1825 FTOUR2 - Free tour II (树上点分治)
- SPOJ1825 FTOUR2 - Free tour II
- spoj 1825 Free tour II
- SPOJ 1825 Free tour II(树的点分治)
- SPOJ 1825 Free tour II 树分治