Solution to a problem P2634 [[National Team] Cong Cong cocoa]

Topic Link

Solution [National Team] Cong Cong cocoa

Topic effect: Given a weighted tree, a tree two points randomly selected and asked path between two points can be long \ (3 \) probability divisible

Dotted rule


Analysis: To calculate the probability, then we can find the number of paths can be long \ (3 \) is divisible, then a total of \ (n ^ 2 \) paths other than \ (gcd \) about points to

About molecule, we have to count all the trees path, so we consider the point of divide and conquer, two exchange order not to consider our handpicked a point in front, and finally the molecules multiplied by \ (2 \) plus \ (n \) that is can (because the same exchange is still considered a two-point scheme)

About dotted rule, according to our statistical sub-tree for each path we have to look at how many paths before and it can be combined length \ (3 \) divisible to

#include <cstdio>
#include <cctype>
#include <vector>
using namespace std;
const int maxn = 2e4 + 100;
inline int read(){
    int x = 0;char c = getchar();
    while(!isdigit(c))c = getchar();
    while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    return x;
}
inline int gcd(int a,int b){return !b ? a : gcd(b,a % b);}
struct Edge{int to,dist;};
vector<Edge> G[maxn];
vector<int> rem;
inline void addedge(int from,int to,int dist){G[from].push_back(Edge{to,dist});}
int maxsiz[maxn],siz[maxn],vis[maxn],dis[maxn],judge[3],tmp[3],n,rt,sum,ans1,ans2;
inline void getroot(int u,int faz = -1){
    siz[u] = 1;maxsiz[u] = 0;
    for(auto e : G[u]){
        int v = e.to;
        if(vis[v] || v == faz)continue;
        getroot(v,u);
        siz[u] += siz[v];
        maxsiz[u] = max(maxsiz[u],siz[v]);
    }
    maxsiz[u] = max(maxsiz[u],sum - siz[u]);
    if(maxsiz[u] < maxsiz[rt])rt = u;
}
inline void getdis(int u,int faz = -1){
    rem.push_back(dis[u]);
    for(auto e : G[u]){
        int v = e.to;
        if(vis[v] || v == faz)continue;
        dis[v] = (dis[u] + e.dist) % 3;
        getdis(v,u);
    }
}
inline void calc(int u){
    for(auto e : G[u]){
        int v = e.to;
        if(vis[v])continue;
        dis[v] = e.dist % 3;
        rem.clear();
        getdis(v,u);
        for(auto x : rem)
            ans1 += judge[(3 - x) % 3];
        for(auto x : rem)
            judge[x]++;
    }
    judge[0] = judge[1] = judge[2] = 0;
}
inline void solve(int u){
    vis[u] = judge[0] = 1;calc(u);
    for(auto e : G[u]){
        int v = e.to;
        if(vis[v])continue;
        sum = siz[v];maxsiz[rt = 0] = 0x7fffffff;
        getroot(v),getroot(rt),solve(rt);
    }
}
int main(){
    n = read();
    for(int u,v,w,i = 1;i < n;i++)
        u = read(),v = read(),w = read(),addedge(u,v,w),addedge(v,u,w);
    sum = n,maxsiz[rt = 0] = 0x7fffffff;
    getroot(1),solve(rt);
    ans1 = ans1 * 2 + n;
    ans2 = n * n;
    int g = gcd(ans1,ans2);
    printf("%d/%d\n",ans1 / g,ans2 / g);
    return 0;
}

Guess you like

Origin www.cnblogs.com/colazcy/p/11797027.html