題目鏈接:Bribes
顯然,樹上差分,分別維護上下路徑,然後對當前路徑討論正反即可。
AC代碼:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10,M=N*2,mod=1e9+7;
int n,m,s[N*10],sz[N],bl[N],pos[N],dep[N],f[N],son[N],cnt,p1[N],p2[N],mi[N*10]={1},res;
int head[N],nex[M],to[M],w[M],tot;
inline void add(int a,int b,int c){to[++tot]=b; nex[tot]=head[a]; w[tot]=c; head[a]=tot;}
void dfs1(int x){
sz[x]=1;
for(int i=head[x];i;i=nex[i]) if(to[i]!=f[x]){
f[to[i]]=x; dep[to[i]]=dep[x]+1;
dfs1(to[i]); sz[x]+=sz[to[i]];
if(sz[to[i]]>sz[son[x]]) son[x]=to[i];
}
}
void dfs2(int x,int belong){
pos[x]=++cnt; bl[x]=belong;
if(son[x]) dfs2(son[x],belong);
for(int i=head[x];i;i=nex[i]) if(dep[to[i]]>dep[x]&&to[i]!=son[x]) dfs2(to[i],to[i]);
}
inline int lca(int x,int y){
while(bl[x]!=bl[y]){
if(dep[bl[x]]<dep[bl[y]]) swap(x,y); x=f[bl[x]];
}
return dep[x]>dep[y]?y:x;
}
void dfs(int x,int fa){
for(int i=head[x];i;i=nex[i]) if(to[i]!=fa){
dfs(to[i],x); p1[x]+=p1[to[i]],p2[x]+=p2[to[i]];
if(w[i]==1) res=(res+mi[p1[to[i]]]-1+mod)%mod;
else if(w[i]==-1) res=(res+mi[p2[to[i]]]-1+mod)%mod;
}
}
signed main(){
cin>>n;
for(int i=1,a,b,c;i<n;i++) scanf("%lld %lld %lld",&a,&b,&c),add(a,b,c),add(b,a,-c);
cin>>m; s[0]=1;
for(int i=1;i<=m;i++) scanf("%lld",&s[i]),mi[i]=mi[i-1]*2%mod;
dfs1(1); dfs2(1,1);
for(int i=1,l;i<=m;i++){
l=lca(s[i],s[i-1]);
p1[s[i-1]]++,p1[l]--,p2[s[i]]++,p2[l]--;
}
dfs(1,1);
cout<<res;
return 0;
}