天天看點

G 林克與寶箱咒語

G 林克與寶箱咒語
/*
keep on going and never give up.
created by legendout
*/
#include<bits/stdc++.h>
using namespace std;
//#define int long long
#define ll __int128
#define endl "\n"
#define fi first
#define se second
#define pb push_back 
#define inf 1e18
#define fast std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const double E = exp(1);
const double PI = acos(-1.0);
const int maxn=1e5+10;
const int mod=1e9+7;
int n,m,k;
long long ans=0;
struct node{
	int v,w;
};
vector<node>e[maxn];
vector<int>ff[maxn],gg[maxn];
int pre[maxn],f[maxn][210],g[maxn][210],sf[210],sg[210]; 

void dfs(int x,int fa){
	f[x][0]=g[x][0]=1;
	for(auto &E:e[x]){
		if(E.v==fa) continue;
		int v=E.v,w=E.w;pre[v]=x;
		dfs(v,x);
		ff[v].resize(k+10),gg[v].resize(k+10);
		for(int i=0;i<=k;i++){
			if(i<k&&w==sf[i]) ff[v][i+1]+=f[v][i];
			else ff[v][i]+=f[v][i];
		}
		for(int i=0;i<=k;i++){
			if(i<k&&w==sg[i]) gg[v][i+1]+=g[v][i];
			else gg[v][i]+=g[v][i];
		}
		for(int i=0;i<=k;i++) f[x][i]+=ff[v][i],g[x][i]+=gg[v][i];
	}
}

void solve(){
	cin>>n>>k;
	for(int i=1;i<n;i++){
		int u,w,v;cin>>u>>v>>w;
		e[u].pb({v,w});
		e[v].pb({u,w});
	}
	for(int i=0;i<k;i++) cin>>sf[i],sg[i]=sf[i];
	reverse(sg,sg+k);
	dfs(1,0);
	ans=0;
	
	for(int x=1;x<=n;x++){
		ans+=g[x][k];
		for(int b=k-1;b>=0;b--) g[x][b]+=g[x][b+1];
		for(auto &E:e[x]){
			if(pre[E.v]!=x) continue;
			for(int b=k-1;b>=0;b--) gg[E.v][b]+=gg[E.v][b+1];
		}
	}
	for(int x=1;x<=n;x++){
		for(auto &E:e[x]){
			if(pre[E.v]!=x) continue;
			for(int a=0;a<=k;a++){
				int b=k-a;
				ans+=(long long)ff[E.v][a]*(g[x][b]-gg[E.v][b]);
			}
		}
	}
	cout<<ans<<endl;
}


signed main(){
//	fast
	int _=1;
//	cin>>_;
	while(_--){
		solve();
	}
}

           

繼續閱讀