标签:
题目链接:hdu 5293 Tree chain problem
维护dp[u], sum[u],dp[u]表示以u为根节点的子树的最优值。sum[u]表示以u节点的所有子节点的dp[v]之和。对于边a,b,w,在LCA(a,b)节点的时候进行考虑。dp[u] = min{dp[u], Sum(a,b) - Dp(a,b) + sum[u] | (ab链上的点,不包括u }
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; #define lowbit(x) ((x)&(-x)) const int maxn = 100005; struct Edge { int u, v, w; }e[maxn]; vector<int> G[maxn]; int N, Q, fenw[maxn], dp[maxn], sum[maxn]; int E, first[maxn], jump[maxn * 2], link[maxn * 2]; int id, idx[maxn], dep[maxn], top[maxn], far[maxn], son[maxn], cnt[maxn]; inline void fenwAdd(int x, int w) { while (x <= N) { fenw[x] += w; x += lowbit(x); } } inline int fenwSum(int x) { int ret = 0; while (x) { ret += fenw[x]; x -= lowbit(x); } return ret; } inline void addEdge(int u, int v) { jump[E] = first[u]; link[E] = v; first[u] = E++; } void dfs (int u, int pre, int d) { dep[u] = d; far[u] = pre; cnt[u] = 1; son[u] = 0; for (int i = first[u]; i + 1; i = jump[i]) { int v = link[i]; if (v == pre) continue; dfs(v, u, d + 1); cnt[u] += cnt[v]; if (cnt[son[u]] < cnt[v]) son[u] = v; } } void dfs (int u, int rot) { top[u] = rot; idx[u] = ++id; if (son[u]) dfs(son[u], rot); for (int i = first[u]; i + 1; i = jump[i]) { int v = link[i]; if (v == far[u] || v == son[u]) continue; dfs(v, v); } } int LCA (int u, int v) { int p = top[u], q = top[v]; while (p != q) { if (dep[p] < dep[q]) { swap(p, q); swap(u, v); } u = far[p]; p = top[u]; } if (dep[u] > dep[v]) swap(u, v); return u; } int query(int u, int v) { int p = top[u], q = top[v], ret = 0; while (p != q) { if (dep[p] < dep[q]) { swap(p, q); swap(u, v); } ret += fenwSum(idx[u]) - fenwSum(idx[p] - 1); u = far[p]; p = top[u]; } if (dep[u] > dep[v]) swap(u, v); ret += fenwSum(idx[v]) - fenwSum(idx[u] - 1); return ret; } void init () { int u, v; E = 0; memset(fenw, 0, sizeof(fenw)); memset(first, -1, sizeof(first)); for (int i = 1; i <= N; i++) G[i].clear(); scanf("%d%d", &N, &Q); for (int i = 1; i < N; i++) { scanf("%d%d", &u, &v); addEdge(u, v); addEdge(v, u); } id = 0; dfs(1, 0, 0); dfs(1, 1); for (int i = 1; i <= Q; i++) { scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w); G[LCA(e[i].u, e[i].v)].push_back(i); } } void solve(int u) { sum[u] = 0; for (int i = first[u]; i + 1; i = jump[i]) { int v = link[i]; if (v == far[u]) continue; solve(v); sum[u] += dp[v]; } dp[u] = sum[u]; for (int i = 0; i < G[u].size(); i++) { int v = G[u][i]; dp[u] = max(dp[u], query(e[v].u, e[v].v) + sum[u] + e[v].w); } fenwAdd(idx[u], sum[u] - dp[u]); } int main () { int cas; scanf("%d", &cas); while (cas--) { init(); solve(1); printf("%d\n", dp[1]); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
hdu 5293 Tree chain problem(树链剖分+树形dp)
标签:
原文地址:http://blog.csdn.net/keshuai19940722/article/details/47175947