HDU 5293 Tree chain problem 树形DP
2017-06-06 23:38
369 查看
题意:
给出一棵\(n\)个节点的树和\(m\)条链,每条链有一个权值。
从中选出若干条链,两两不相交,并且使得权值之和最大。
分析:
题解
给出一棵\(n\)个节点的树和\(m\)条链,每条链有一个权值。
从中选出若干条链,两两不相交,并且使得权值之和最大。
分析:
题解
#include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <set> #include <vector> #include <iostream> #include <string> using namespace std; #define REP(i, a, b) for(int i = a; i < b; i++) #define PER(i, a, b) for(int i = b - 1; i >= a; i--) #define SZ(a) ((int)a.size()) #define MP make_pair #define PB push_back #define EB emplace_back #define ALL(a) a.begin(), a.end() typedef long long LL; typedef pair<int, int> PII; const int maxn = 100000 + 10; int n, m; vector<int> G[maxn], Q[maxn]; int u[maxn], v[maxn], w[maxn]; int l[maxn], r[maxn], dfs_clock; int dp[maxn], sum[maxn]; int dep[maxn]; int anc[maxn][20]; void dfs(int u, int fa) { l[u] = ++dfs_clock; anc[u][0] = fa; for(int i = 0; anc[u][i]; i++) anc[u][i+1] = anc[anc[u][i]][i]; dep[u] = dep[fa] + 1; for(int v : G[u]) if(v != fa) { dfs(v, u); } r[u] = ++dfs_clock; } int LCA(int u, int v) { if(dep[u] < dep[v]) swap(u, v); PER(i, 0, 20) if(dep[anc[u][i]] >= dep[v]) u = anc[u][i]; if(u == v) return u; PER(i, 0, 20) if(anc[u][i] != anc[v][i]) u = anc[u][i], v = anc[v][i]; return anc[u][0]; } int C[maxn << 1]; #define lowbit(x) (x&(-x)) void add(int x, int v) { while(x <= n * 2) { C[x] += v; x += lowbit(x); } } int query(int x) { int ans = 0; while(x) { ans += C[x]; x -= lowbit(x); } return ans; } void init() { REP(i, 1, n + 1) G[i].clear(), Q[i].clear(); memset(anc, 0, sizeof(anc)); dfs_clock = 0; memset(C, 0, sizeof(C)); memset(dp, 0, sizeof(dp)); memset(sum, 0, sizeof(sum)); } void upd(int& a, int b) { if(a < b) a = b; } void solve(int x) { for(int y : G[x]) if(y != anc[x][0]) { solve(y); sum[x] += dp[y]; } dp[x] = sum[x]; for(int q : Q[x]) { upd(dp[x], sum[x] + query(l[u[q]]) + query(l[v[q]]) + w[q]); } add(l[x], sum[x] - dp[x]); add(r[x], dp[x] - sum[x]); } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d%d", &n, &m); init(); REP(i, 1, n) { int u, v; scanf("%d%d", &u, &v); G[u].PB(v); G[v].PB(u); } dfs(1, 0); REP(i, 0, m) { scanf("%d%d%d", u + i, v + i, w + i); int lca = LCA(u[i], v[i]); Q[lca].PB(i); } solve(1); printf("%d\n", dp[1]); } return 0; }
相关文章推荐
- hdu 5293 Tree chain problem(树链剖分+树形dp)
- 多校第一场 1006 hdu 5293 Tree chain problem(离线LCA+时间戳+树形dp)
- HDU 5293 Tree chain problem - 树形dp&树状数组优化
- HDU 5293 Tree chain problem【树形DP】
- HDU 5293 Tree chain problem [树链剖分+线段树+树形DP]
- HDU 5293 Tree chain problem(树形DP+树链剖分+LCA)
- hdu 5293 Tree chain problem(15多校第一场1006)(树形dp+树状数组+LCA)
- HDOJ 5293 Tree chain problem LCA+树链剖分+树形DP
- HDU 5293 Tree chain problem(树形DP+树链剖分)
- HDU 5293 Tree chain problem(数链问题)【LCA+树形dp+dfs序+树状数组】
- 【HDU】5293 Tree chain problem【DP+LCA】
- HDU 5293 Tree chain problem 树形DP+LCA+树链剖分+线段树
- (中等) HDU 5293 Tree chain problem,树链剖分+树形DP。
- HDU5293:Tree chain problem(树形dp & LCA)
- 【DP】 HDOJ 5293 Tree chain problem
- 2015多校第一场1006 hdu 5293 Tree chain problem
- 【HDU 5233】Tree chain problem (树形DP+树剖+线段树|树状数组)最大权不相交树链集
- HDU 5293(Tree chain problem-树链剖分)
- 树形DP - hdu5293 Tree chain problem
- hdu 5293 Tree chain problem【树状dp+dfs序+树状数组】