zoukankan      html  css  js  c++  java
  • BZOJ-2152 聪聪可可 【点分治】

    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。
    
    
    思路:
    树上统计路径问题,对于20000个点,点分治算法足以解决。

    Code:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define INF 0x3f3f3f3f
     4 #define M(a, b) memset(a, b, sizeof(a))
     5 const int maxn = 20000 + 5;
     6 int sum, ans, n, root, d[maxn], mod[3], son[maxn], f[maxn];
     7 bool vis[maxn];
     8 struct Node {
     9     int to, w;
    10 };
    11 vector<Node> G[maxn*2];
    12 
    13 int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);}
    14 
    15 void getroot(int x, int fa) {
    16     f[x] = 0, son[x] = 1;
    17     for (int i = 0; i < G[x].size(); ++i) {
    18         int v = G[x][i].to;
    19         if (vis[v] || v == fa) continue;
    20         getroot(v, x);
    21         son[x] += son[v];
    22         f[x] = max(f[x], son[v]);
    23     }
    24     f[x] = max(f[x], sum-son[x]);
    25     if (f[x] < f[root]) root = x;
    26 }
    27 
    28 void getdeep(int x, int fa) {
    29     mod[d[x]]++;
    30     for (int i = 0; i < G[x].size(); ++i) {
    31         int v = G[x][i].to;
    32         if (vis[v] || v == fa) continue;
    33         d[v] = (d[x] + G[x][i].w) % 3;
    34         getdeep(v, x);
    35     }
    36 }
    37 
    38 int cal(int x, int now) {
    39     d[x] = now;
    40     mod[0] = mod[1] = mod[2] = 0;
    41     getdeep(x, 0);
    42     return mod[1]*mod[2]*2 + mod[0]*mod[0];
    43 }
    44 
    45 void work(int x) {
    46     ans += cal(x, 0);
    47     vis[x] = 1;
    48     for (int i = 0; i < G[x].size(); ++i) {
    49         int v = G[x][i].to;
    50         if (vis[v]) continue;
    51         ans -= cal(v, G[x][i].w);
    52         sum = son[v];
    53         root = 0;
    54         getroot(v, 0);
    55         work(root);
    56     }
    57 }
    58 
    59 int main() {
    60     ios::sync_with_stdio(false);
    61     while(cin >> n) {
    62         int a, b, c;
    63         memset(vis, 0, sizeof(vis));
    64         for (int i = 1; i <= n; ++i) G[i].clear();
    65         for (int i = 1; i < n; ++i) {
    66             cin >> a >> b >> c; c %= 3;
    67             G[a].push_back(Node{b, c});
    68             G[b].push_back(Node{a, c});
    69         }
    70         sum = n;
    71         ans = 0;
    72         root = 0;
    73         f[root] = INF;
    74         getroot(1, 0);
    75         work(root);
    76         int all = n * n;
    77         int e = gcd(all, ans);
    78         cout << ans/e << "/" << all/e << endl;
    79     }
    80 
    81     return 0;
    82 }
  • 相关阅读:
    Spring初次整体了解及一篇SpringBoot的稿子。。。
    JAVA日志框架log4j和slf4j
    初学SpringBoot之三
    初学SpringBoot之二
    初学SpringBoot之一
    (转)SWITCH_ROOT
    (转)initrd和initramfs的区别
    (转)三星HDMI驱动框架解析
    (转)linux内存分析
    (转)linux中挂载IMG文件
  • 原文地址:https://www.cnblogs.com/robin1998/p/6538492.html
Copyright © 2011-2022 走看看