maki和tree
maki和tree
http://www.nowcoder.com/questionTerminal/78ad8790111440009f73737419c5aae8
对于每一个黑色结点,定义为一棵树的根
比如此时的路径有共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; }