题解:
这是一道比较简单的题目。
我们发现其实黑边是没有用的,三个点只要中间的到两边都有红边相连就好了。
那么我们可以容斥一下。把所有的黑边都并查集到一起,形成好多块。
那么答案=任选三个数的方案数-一个块中选三个的方案数-一个块中选一个,另一个中选两个的方案数。
注意并查集最后的fa数组并不是这个点最后的fa,要再做一次并查集。
代码如下:
#include<cstdio>
#include<string>
using namespace std;
const int maxn=50005,tt=1000000007;
int n,fa[maxn],sum[maxn];
long long ans;
inline int read(){
int x=0; char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x;
}
int getfa(int x){if (fa[x]!=x) fa[x]=getfa(fa[x]); return fa[x];}
void add(int x,int y){
int fax=getfa(x),fay=getfa(y);
if (fax!=fay) fa[fax]=fay;
}
int main(){
n=read();
for (int i=1;i<=n;i++) fa[i]=i;
for (int i=1;i<n;i++) {
int x=read(),y=read();
char ch=getchar(); while (ch!='r'&&ch!='b') ch=getchar();
if (ch=='b') add(x,y);
}
ans=1ll*n*(n-1)*(n-2)/6%tt;
for (int i=1;i<=n;i++) sum[getfa(i)]++;
for (int i=1;i<=n;i++)
if (fa[i]==i) {
if (sum[i]>=3) ans=(ans+tt-1ll*sum[i]*(sum[i]-1)*(sum[i]-2)/6%tt)%tt;
if (sum[i]>=2) ans=(ans+tt-1ll*sum[i]*(sum[i]-1)/2%tt*(n-sum[i])%tt)%tt;
}
printf("%lld\n",ans);
return 0;
}