专栏首页数据结构与算法BZOJ2152: 聪聪可可(点分治)

BZOJ2152: 聪聪可可(点分治)

Time Limit: 3 Sec  Memory Limit: 259 MB

Submit: 4902  Solved: 2572

[Submit][Status][Discuss]

Description

聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃、两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已经玩儿腻了这种低智商的游戏。他们的爸爸快被他们的争吵烦死了,所以他发明了一个新游戏:由爸爸在纸上画n个“点”,并用n-1条“边”把这n个“点”恰好连通(其实这就是一棵树)。并且每条“边”上都有一个数。接下来由聪聪和可可分别随即选一个点(当然他们选点时是看不到这棵树的),如果两个点之间所有边上数的和加起来恰好是3的倍数,则判聪聪赢,否则可可赢。聪聪非常爱思考问题,在每次游戏后都会仔细研究这棵树,希望知道对于这张图自己的获胜概率是多少。现请你帮忙求出这个值以验证聪聪的答案是否正确。

Input

输入的第1行包含1个正整数n。后面n-1行,每行3个整数x、y、w,表示x号点和y号点之间有一条边,上面的数是w。

Output

以即约分数形式输出这个概率(即“a/b”的形式,其中a和b必须互质。如果概率为1,输出“1/1”)。

Sample Input

5 1 2 1 1 3 2 1 4 1 2 5 3

Sample Output

13/25 【样例说明】 13组点对分别是(1,1) (2,2) (2,3) (2,5) (3,2) (3,3) (3,4) (3,5) (4,3) (4,4) (5,2) (5,3) (5,5)。 【数据规模】 对于100%的数据,n<=20000。

HINT

Source

点分治的模板题

我们只需要统计出每个点在$\pmod 3$意义下的距离即可

每个点的答案为$sum[1] * sum[2] * 2 + sum[0] * sum[3]$

最后总的答案和$n^2$取个gcd就行

#include<cstdio>
#include<vector>
#include<algorithm>
#define Pair pair<int, int> 
#define MP(x, y) make_pair(x, y)
using namespace std;
const int MAXN = 20001, INF = 1e9 + 10;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9'){if(c == '-')f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
vector<Pair> v[MAXN];
int N;
int siz[MAXN], maxsiz[MAXN], vis[MAXN], root, Sum, Mx, ans, dis[MAXN];
void FindRoot(int x, int fa) {
    siz[x] = 1; maxsiz[x] = 0;
    for(int i = 0; i < v[x].size(); i++) {
        int to = v[x][i].first, w = v[x][i].second;
        if(to == fa || vis[to]) continue;
        FindRoot(to, x);
        siz[x] += siz[to];
        if(siz[to] > maxsiz[x]) maxsiz[x] = siz[to];
    }
    maxsiz[x] = max(maxsiz[x], Sum - siz[x]);
    if(maxsiz[x] < Mx) Mx = maxsiz[x], root = x;
}
void GetRoot(int num, int x) {
    Sum = num; Mx = INF; root = 0; FindRoot(x, 0);    
}
int num = 0;
void GetDis(int x, int fa, int cur) {
    dis[++num] = cur % 3;
    for(int i = 0; i < v[x].size(); i++) {
        int to = v[x][i].first, w = v[x][i].second;
        if(to == fa || vis[to]) continue;
        GetDis(to, x, (cur + w) % 3); 
    }
}
int calc(int x, int len) {
    num = 0;
    GetDis(x, 0, len);
    int sum[3] = {};
    for(int i = 1; i <= num; i++) sum[dis[i] % 3]++;
    return sum[1] * sum[2] * 2 + sum[0] * sum[0];
}
void Solve(int x) {
    vis[x] = 1;
    ans += calc(x, 0);
    for(int i = 0; i < v[x].size(); i++) {
        int to = v[x][i].first, w = v[x][i].second;
        if(vis[to]) continue;
        ans -= calc(to, w);
        GetRoot(siz[to], to);
        Solve(root);
    }
}
int main() {
#ifdef WIN32
    freopen("a.in", "r", stdin);
#endif
    N = read();
    for(int i = 1; i <= N - 1; i++) {
        int x = read(), y = read(), z = read();
        v[x].push_back(MP(y, z));
        v[y].push_back(MP(x, z));
    }
    GetRoot(N, 1);
    Solve(root);
    int gcd = __gcd(ans, N * N);
    printf("%d/%d", ans / gcd, N * N / gcd);
    return 0;
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • BZOJ3143: [Hnoi2013]游走(期望DP 高斯消元)

    Description 一个无向连通图,顶点从1编号到N,边从1编号到M。  小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当...

    attack
  • 树上莫队算法

    attack
  • 2017.5.13阶段模拟考试

    预计分数:100+50(其实感觉自己写的对)+100 实际分数:100+0+100 P1149 火柴棒等式 题目描述 给你n根火柴棍,你可以拼出多少个形如“A+...

    attack
  • 2017.5.13阶段模拟考试

    预计分数:100+50(其实感觉自己写的对)+100 实际分数:100+0+100 P1149 火柴棒等式 题目描述 给你n根火柴棍,你可以拼出多少个形如“A+...

    attack
  • 2019河南科技学院发现杯

    来到学校后第一次参加算法比赛,听学长说去年的难度非常高,所以这次比赛目标就是得到分数。但今年的难度整体偏低,第八题做的比较懵,第十题不会做(连题都看不懂 ),其...

    dejavu1zz
  • 通吃岛屿问题

    在秋招及实习期间发现岛屿问题在面试中会被经常问到,本节来把leetcode上的所有岛屿问题通吃一遍。

    公众号guangcity
  • LeetCode 323. 无向图中连通分量的数目(并查集)

    给定编号从 0 到 n-1 的 n 个节点和一个无向边列表(每条边都是一对节点),请编写一个函数来计算无向图中连通分量的数目。

    Michael阿明
  • 挑战程序竞赛系列(23):3.2折半枚举

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.n...

    用户1147447
  • POJ 刷题系列:3349. Snowflake Snow Snowflakes

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/...

    用户1147447
  • codeforces329B(bfs)

    由于猎人事先知道我们行走的路线,所以猎人们可以先走到终点前等待,可以使用bfs预处理出终点到各个点之间的距离,如果猎人到终点的距离小于等于我们从起点到终点的距离...

    dejavu1zz

扫码关注云+社区

领取腾讯云代金券