QZC树的分治论文第二道例题, 自己想了想觉得没什么思路, 后来看了论文中的解法看到中间时想到了一个线段树优化dp的解法, 论文中也提到的令dp[L] 表示从当前根结点向下经过L个crowded节点的最长路径值,在进行分治时用两个dp数组, dp1表示当前根节点前i - 1棵子树的dp值, dp2表示第i棵子树的dp值,用线段树维护dp1的值,我们每次dfs一个子树时得到dp2的值, 然后用
dp2[j] + max(dp1[k]) 0 <= k <= m - j - is[root]( m表示最多经过m个crowed节点)更新ans, 然后再用dp2更新dp1, 大致就是这样的一个做法。。。
#include <iostream>
#include <cstdio>
#include <queue>
#include <map>
#include <algorithm>
#include <cstring>
#include <cstdlib>
using namespace std;
typedef long long LL;
inline int readint() {
char c = getchar();
while (!isdigit(c)) c = getchar();
int x = 0;
while (isdigit(c)) {
x = x * 10 + c - '0';
c = getchar();
}
return x;
}
inline int lowbit(int t) {
return t & (-t);
}
const int N = 200015;
const int M = N << 1;
const int INF = 2000000001;
#define fi first
#define se second
int n, is[N];
int head[N], next[M], to[M], W[M];
bool done[N];
int size[N], d[N];
int dp1[N], dp2[N];
int sub[N];
int E, tot, root, tdfn;
int K;
vector<int> vec;
int ans;
#define lch rt << 1, L, mid
#define rch rt << 1 | 1, mid + 1, R
struct SegmentTree {
int maxv[N << 2];
int n;
void init(int n) {
this->n = n;
build(1, 0, n);
}
inline void push_up(int rt) {
maxv[rt] = max(maxv[rt << 1], maxv[rt << 1 | 1]);
}
void build(int rt, int L, int R) {
if (L == R) {
maxv[rt] = dp1[L];
return;
}
int mid = L + R >> 1;
build(lch), build(rch);
push_up(rt);
}
void update(int rt, int L, int R, int p, int v) {
if (L == R) {
maxv[rt] = v;
return;
}
int mid = L + R >> 1;
if (p <= mid)
update(lch, p, v);
else
update(rch, p, v);
push_up(rt);
}
int query(int rt, int L, int R, int l, int r) {
if (l <= L && R <= r) {
return maxv[rt];
}
int mid = L + R >> 1;
int res = -INF;
if (l <= mid)
res = max(res, query(lch, l, r));
if (r > mid)
res = max(res, query(rch, l, r));
return res;
}
void op1(int p, int v) {
update(1, 0, n, p, v);
}
int op2(int l, int r) {
if (l > r)
return -INF;
return query(1, 0, n, l, r);
}
}T;
void init() {
for (int i = 1; i <= n; i++)
head[i] = -1, done[i] = 0, is[i] = 0;
E = 0;
ans = -INF;
}
void add(int u, int v, int w) {
W[E] = w, to[E] = v, next[E] = head[u], head[u] = E++;
W[E] = w, to[E] = u, next[E] = head[v], head[v] = E++;
}
void gao(int u, int fa) {
sub[tot] = u;
int t = tot++;
int omax = 0;
for (int i = head[u]; i != -1; i = next[i]) {
int v = to[i];
if (!done[v] && v != fa) {
gao(v, u);
omax = max(omax, size[v]);
}
}
size[u] = tot - t;
if (size[u] > 1)
d[u] = omax;
}
int center(int u) {
tot = 0;
gao(u, 0);
if (tot == 1) return u;
int key = N;
int res;
for (int k = 0; k < tot; k++) {
int v = sub[k];
d[v] = max(tot - size[v], d[v]);
if (size[v] > 1 && d[v] < key) {
key = d[v];
res = v;
}
}
return res;
}
void dfs(int u, int fa, int cnt, int sum) {
if (cnt > K) return;
if (fa) {
if (dp2[cnt] == -INF || dp2[cnt] < sum) {
if (dp2[cnt] == -INF) vec.push_back(cnt);
dp2[cnt] = sum;
}
}
for (int i = head[u]; i != -1; i = next[i]) {
int v = to[i];
if (v != fa && !done[v]) {
dfs(v, u, cnt + is[v], sum + W[i]);
}
}
if (fa == root) {
if (u != to[head[root]]) {
for (int i = 0; i < vec.size(); i++) {
int t = vec[i];
if (K - is[root] - t >= 0)
ans = max(ans, T.op2(0, K - is[root] - t) + dp2[t]);
}
}
for (int i = 0; i < vec.size(); i++) {
int t = vec[i];
if (dp2[t] > dp1[t]) {
dp1[t] = dp2[t];
T.op1(t, dp1[t]);
}
dp2[t] = -INF;
}
vec.clear();
}
}
void solve(int u) {
root = center(u);
if (tot == 1) {
done[u] = 1;
return;
}
fill(dp1, dp1 + tot + 1, -INF);
fill(dp2, dp2 + tot + 1, -INF);
T.init(tot);
tdfn = 0;
dfs(root, 0, 0, 0);
for (int i = 0; i <= tot; i++)
if (i + is[root] <= K)
ans = max(ans, dp1[i]);
done[root] = 1;
for (int i = head[root]; i != -1; i = next[i])
if (!done[to[i]])
solve(to[i]);
}
int main() {
/*
int SIZE = 256 << 20; // 256MB
char *p = (char*)malloc(SIZE) + SIZE;
__asm__("movl %0, %%esp\n" :: "r"(p) );*/
int m, u, v, w, t;
n = readint(), K = readint(), m = readint();
init();
for (int i = 0; i < m; i++) {
t = readint();
is[t] = 1;
}
for (int i = 0; i < n - 1; i++) {
u = readint();
v = readint();
scanf("%d", &w);
add(u, v, w);
}
solve(1);
for (int i = 1; i <= n; i++)
if (is[i] <= K && ans < 0) {
ans = 0;
break;
}
printf("%d\n", ans);
return 0;
}