There are two children playing games. Each of them gets a point in the tree. If the sum of the path lengths between the two points is a multiple of 3, Cong will win, otherwise, he will lose. This tree is provided to calculate the probability of a Cong win. The answer is expressed by the score.
Idea: The data range is 2 W. Certainly, it cannot be enumeration points and then LCA. So we can only divide the data. This is still a more common point Partitioning Problem, but there is a point to note that when calculating the distance between two points, I initially thought that the enumeration is directly n ^ 2, then record. However, the time complexity will seriously degrade. However, it is noted that we only need the number of % 3 = 0, followed by % 3 = 0, % 3 = 1, % 3 = 2. Therefore, we only need to count the number of the three numbers.
PS: the _ GCD function in algorithm is used. It is said that it will not be used during the examination...
Code:
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define MAX 20010#define INF 0x3f3f3f3fusing namespace std;int points;int head[MAX],total;int next[MAX << 1],aim[MAX << 1],length[MAX << 1];int size[MAX],_size,_total,c;bool v[MAX];int cnt[MAX],dis[3],p;inline void Add(int x,int y,int len){next[++total] = head[x];aim[total] = y;length[total] = len % 3;head[x] = total;}inline void GetRoot(int x,int last){size[x] = 1;int max_size = 0;for(int i = head[x]; i; i = next[i]) {if(aim[i] == last || v[aim[i]])continue;GetRoot(aim[i],x);size[x] += size[aim[i]];max_size = max(max_size,size[aim[i]]);}max_size = max(max_size,_total - size[x]);if(_size > max_size)_size = max_size,c = x;}inline void GetDis(int x,int last,int len){++dis[len % 3];for(int i = head[x]; i; i = next[i]) {if(aim[i] == last || v[aim[i]])continue;GetDis(aim[i],x,len + length[i]);}}inline int Count(int x,int len){int re = 0;p = 0;memset(dis,0,sizeof(dis));GetDis(x,0,len);re += dis[0] * dis[0];re += dis[1] * dis[2] << 1;return re;}inline void Work(int x){_size = INF;_total = size[x] ? size[x]:points;GetRoot(x,0);x = c;v[x] = true;cnt[x] = Count(x,0);for(int i = head[x]; i; i = next[i]) {if(v[aim[i]])continue;cnt[x] -= Count(aim[i],length[i]);Work(aim[i]);}}int main(){cin >> points;for(int x,y,z,i = 1; i < points; ++i) {scanf("%d%d%d",&x,&y,&z);Add(x,y,z),Add(y,x,z);}Work(1);int ans = 0;for(int i = 1; i <= points; ++i)ans += cnt[i];cout << ans / __gcd(ans,points * points) << '/' << points * points / __gcd(ans,points * points) << endl;return 0;}
Bzoj 2152 intelligent cocoa tree governance