对于每一个黑色结点,定义为一棵树的根
比如此时的路径有共4条+
共3条
那么对于一个以B为根的树
答案等于1+3 + 1*3
也就是
等效为
而x两两相乘求会增加复杂度,所以转换为 (x表示不含黑色结点的子树的个数,n表示该黑色结点的子树棵树)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn = 1e5+5;
const int inf = 0x3f3f3f3f;
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return f*x;
}
char s[maxn];
std::vector<int> G[maxn];
ll sum,t1,t2,ans;
void dfs(int p,int fa){
if(s[p] == 'B')return;
sum++;
for(int i = 0; i < G[p].size(); i++)
if(G[p][i] != fa)dfs(G[p][i],p);
}
int main(){
int n = read();
scanf("%s",s+1);
for(int i = 1; i < n; i++){
int x,y;
x = read(),y = read();
G[x].push_back(y);
G[y].push_back(x);
}
for(int i = 1; i <= n; i++){
t1 = 0,t2 = 0;//t1黑点的所有点延续下去,连续白色的个数
if(s[i] == 'B'){
for(int j = 0; j < G[i].size(); j++){
sum = 0;//表示与黑色点连接的一个点延续下去,连续白色的个数
dfs(G[i][j],G[i][j]);
ans += sum;
t1 += sum;
t2 += sum * sum;
}
ans += (t1 * t1 - t2)/2;
}
}
printf("%lld\n",ans);
return 0;
}


京公网安备 11010502036488号