解法
设f[i]表示覆盖了i的子树和i的返祖边的最小代价,那么答案就是
∑
i
∈
s
o
n
[
1
]
f
[
i
]
\sum_{i\in son[1]} f[i]
∑i∈son[1]f[i],但是f[i]的方案不一定是最终的最优方案,如果某个方案可以向上延伸的更长,即使现在代价比较高,也有可能是最终更优的方案,所以我们需要维护所有有可能成为答案的方案。然后再给当前点选出一个最小的作为f。
因为要选最小值,所以考虑使用小根堆。
转移的方法:对于
x
∈
s
o
n
[
y
]
x\in son[y]
x∈son[y],从x转移到y,对于x的小根堆里的一个方案:如果它不能延伸到y的父亲,就需要把它删了,否则这个方案(设其权值为val)会对y提供一种权值为
v
a
l
+
∑
z
∈
s
o
n
[
y
]
f
[
z
]
−
f
[
x
]
val+\sum_{z\in son[y]} f[z]-f[x]
val+∑z∈son[y]f[z]−f[x],延伸位置不变的方案。
然后对于需要删除的方案,不需要直接删除,而是在其成为堆顶以后再删除。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e5+5;
inline int read(){
char c=getchar();int t=0,f=1;
while((!isdigit(c))&&(c!=EOF)){if(c=='-')f=-1;c=getchar();}
while((isdigit(c))&&(c!=EOF)){t=(t<<3)+(t<<1)+(c^48);c=getchar();}
return t*f;
}
int n,m;
struct edge{
int v,p;
}e[maxn<<1];
int h[maxn],cnt;
inline void add(int a,int b){
e[++cnt].p=h[a];
e[cnt].v=b;
h[a]=cnt;
e[++cnt].p=h[b];
e[cnt].v=a;
h[b]=cnt;
}
typedef pair<int,int> pii;
vector<pii> g[maxn];
int dep[maxn];
ll f[maxn],ans;
struct node{
pair<ll,int> x;
ll z;
int l,r,fa,d;
}t[maxn];
#define fi first
#define se second
inline void add(int x,ll k){
if(x)t[x].x.fi+=k,t[x].z+=k;
}
inline void pushdown(int x){
add(t[x].l,t[x].z);
add(t[x].r,t[x].z);
t[x].z=0;
}
inline int merge(int x,int y){
if(!x||!y)return x|y;
if(t[x].x>t[y].x)swap(x,y);
if(t[x].z)
pushdown(x);
t[x].r=merge(t[x].r,y);
t[t[x].r].fa=x;
if(t[t[x].r].d>t[t[x].l].d)swap(t[x].l,t[x].r);
t[x].d=t[t[x].r].d+1;
return x;
}
int tot,rt[maxn];
void dfs(int u,int fa){
dep[u]=dep[fa]+1;
for(auto o:g[u]){tot++;
t[tot].x=o,t[tot].d=1;rt[u]=merge(rt[u],tot);
}
ll s=0;
for(int i=h[u];i;i=e[i].p){
int v=e[i].v;
if(v==fa)continue;
dfs(v,u);s+=f[v];
add(rt[v],-f[v]);rt[u]=merge(rt[u],rt[v]);
}
add(rt[u],s);
while(rt[u]&&dep[t[rt[u]].x.se]>=dep[u]){
if(t[rt[u]].z)
pushdown(rt[u]);
rt[u]=merge(t[rt[u]].l,t[rt[u]].r);
}
if(!rt[u]){puts("-1");exit(0);}
f[u]=t[rt[u]].x.fi;
}
signed main(){
n=read(),m=read();
for(int i=1;i<n;i++){
int x=read(),y=read();
add(x,y);
}
for(int i=1;i<=m;i++){
int x=read(),y=read(),z=read();
g[x].push_back(pii(z,y));
}
dep[1]=1;
for(int i=h[1];i;i=e[i].p){
int v=e[i].v;
dfs(v,1);ans+=f[v];
}
printf("%lld\n",ans);
return 0;
}