(http://acm.hust.edu.cn/vjudge/contest/view.action?cid=106364#problem/A)
题意:给定一棵树,一些链,选出最多的链不相交。
解法:定义 sum[u] = sim(dp[v]) ( v = son[u] )
dp[u]为u这颗子树,最多能选的链数。
当有一条链a,b,lca(a,b)=u
dp[u] = sum[u] - dp[a1] + sum[a1] - dp[a2] … + sum[a]
这样就可以用树链剖分搞啦~
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <queue>
//#include <tr1/unordered_set>
//#include <tr1/unordered_map>
#include <bitset>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define inf 1e9
#define debug(a) cout << #a" = " << (a) << endl;
#define debugarry(a, n) for (int i = 0; i < (n); i++) { cout << #a"[" << i << "] = " << (a)[i] << endl; }
#define clr(x, y) memset(x, y, sizeof x)
#define ll long long
#define ull unsigned long long
#define FOR(i,a,b) \
for(i=a;a<b?i<=b:i>=b;a<b?i++:i--)
const int maxn = 100000+30;
struct sad{
int to,next;
}G[maxn<<2];
int h[maxn],si;
void add(int u,int v){
G[si].to=v;
G[si].next=h[u];
h[u]=si++;
}
int siz[maxn],dep[maxn];
int fa[maxn],son[maxn],top[maxn];
void dfs1(int u,int f,int d)
{
fa[u]=f;
dep[u]=d;
siz[u]=1;
son[u]=-1;
for(int i=h[u];~i;i=G[i].next)
{
int v=G[i].to;
if(v!=f){
dfs1(v,u,d+1);
siz[u]+=siz[v];
if(son[u]==-1||siz[son[u]]<siz[v])
son[u]=v;
}
}
}
int p[maxn],fp[maxn],pos;
void dfs2(int u,int sf){
top[u]=sf;
p[u]=pos++;
fp[p[u]]=u;
if(son[u]==-1) return ;
dfs2(son[u],sf);
for(int i=h[u];~i;i=G[i].next)
{
int v=G[i].to;
if(son[u]!=v&&fa[u]!=v)
dfs2(v,v);
}
}
int rs[maxn];
void upp(int x,int p)
{
while(x<=pos)
{
rs[x] += p;
x += x&-x;
}
}
int get(int x){
int ret=0;
while(x)
{
ret+=rs[x];
x-=x&-x;
}
return ret;
}
int Query(int u,int v)
{
int ret=0,f1=top[u],f2=top[v];
while(f1^f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(u,v);
}
ret += get(p[u]) - get(p[f1]-1);
u=fa[f1];
f1=top[u];
}
if( dep[u] > dep[v] ) swap(u,v);
return ret += get(p[v]) - get(p[u]-1);
}
int lca(int u,int v){
int f1=top[u],f2=top[v];
while(f1^f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(u,v);
}
u=fa[f1];
f1=top[u];
}
if( dep[u] > dep[v] ) swap(u,v);
return u;
}
void init()
{
clr(h,-1);
si=0;
pos=1;
}
int uu[maxn],vv[maxn],val[maxn];
int dp[maxn] , sum[maxn];
vector<int>Q[maxn];
void dfs(int u,int f)
{
for(int i=h[u];~i;i=G[i].next)
{
int v = G[i].to;
if( v != f )
{
dfs(v,u);
sum[u] += dp[v];
}
}
upp(p[u],sum[u]);
dp[u] = sum[u];
for(int i=0;i<Q[u].size();i++)
{
int j=Q[u][i];
dp[u] = max( dp[u] , Query(uu[j],vv[j]) + val[j] );
}
upp(p[u],-dp[u]);
}
int main()
{
// freopen("input.txt","r",stdin);
int T;
scanf("%d",&T);
int n,m;
while(T--){
scanf("%d%d",&n,&m);
init();
int u,v;
for(int i=0;i<n-1;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
clr(dp,0);
clr(sum,0);
clr(rs,0);
for(int i=1;i<=n;i++)
Q[i].clear();
dfs1(1,-1,1);
dfs2(1,1);
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&uu[i],&vv[i],&val[i]);
Q[lca(uu[i],vv[i])].push_back(i);
}
dfs(1,-1);
printf("%d\n",dp[1]);
}
return 0;
}