一个容斥的做法,对于树上连通块问题,转化为点的贡献之和减去边的贡献之和
所以这题就简单了,统计所有绿点的贡献和边的两端都是绿点的边的贡献
Code:
#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
inline int add(int x,int y){x+=y;if(x>=mod) x-=mod;return x;}
inline int dec(int x,int y){x-=y;if(x<0) x+=mod;return x;}
inline int mul(int x,int y){return (ll)x*y%mod;}
inline void inc(int &x,int y){x+=y;if(x>=mod) x-=mod;}
inline void Dec(int &x,int y){x-=y;if(x<0) x+=mod;}
inline void Mul(int &x,int y){x=mul(x,y);}
const int N=2e3+5;
int vis[N<<1],nxt[N<<1],head[N],c[N<<1],tot=0;
int rd[N],bl[N],W,col[N];
inline void add(int x,int y,int z){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;c[tot]=z;}
inline void dfs(int v,int fa,int dep){
if(dep>W) {rd[v]=bl[v]=0;return;}
pt[v]=(col[v]!=3),pb[v]=(col[u]!=1);
for(int i=head[v];i;i=nxt[i]){
int y=vis[i];
if(y==fa) continue;
dfs(y,v,dep+c[i]);
Mul(rd[v],rd[y]+1);Mul(bl[v],bl[y]+1);
}
}
int ans=0;
inline void point(int x){dfs(x,0,0);inc(ans,mul(rd[x],bl[x]));}
inline void edge(int x,int y,int z){dfs(x,y,z);dfs(y,x,z);Dec(ans,mul(mul(rd[x],bl[x]),mul(rd[y],bl[y])));}
struct E{int x,y,z;}e[N];
int main(){
int n=read();W=read();
for(int i=1;i<=n;i++){
char ch=getchar();
if(ch=='R') col[i]=1;
if(ch=='G') col[i]=2;
if(ch=='B') col[i]=3;
}
for(int i=1;i<n;i++){
e[i].x=read(),e[i].y=read(),e[i].z=read();
add(e[i].x,e[i].y,e[i].z);add(e[i].y,e[i].x,e[i].z);
}
for(int i=1;i<=n;i++) if(col[i]==2) point(i);
for(int i=1;i<n;i++) if(col[e[i].x]==2 && col[e[i].y]==2) edge(e[i].x,e[i].y,e[i].z);
cout<<ans;
return 0;
}