zoukankan      html  css  js  c++  java
  • 【bzoj2152】聪聪可可 点分治

    【bzoj2152】聪聪可可

    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。
     
    询问多少点对之间路径和是3的倍数,这样就是模数什么的搞一搞就ok了。
     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<iostream>
     6 #define N 20007
     7 #define inf 1000000009
     8 using namespace std;
     9 
    10 int n,k;
    11 int ans,id,total;
    12 int siz[N],f[N],deep[N],dis[N],vis[N],num[4];
    13 int cnt,head[N],next[N*2],rea[N*2],val[N*2];
    14 
    15 void add(int u,int v,int fee)
    16 {
    17     next[++cnt]=head[u];
    18     head[u]=cnt;
    19     rea[cnt]=v;
    20     val[cnt]=fee;
    21 }
    22 void get_heart(int u,int fa)
    23 {
    24     siz[u]=1,f[u]=0;
    25     for (int i=head[u];i!=-1;i=next[i])
    26     {
    27         int v=rea[i];
    28         if (v==fa||vis[v])continue;
    29         get_heart(v,u);
    30         siz[u]+=siz[v];
    31         f[u]=max(f[u],siz[v]);
    32     }
    33     f[u]=max(total-siz[u],f[u]);
    34     if (f[u]<f[id]) id=u;
    35 }
    36 void get_dis(int u,int fa)
    37 {
    38     num[dis[u]%3]++;
    39     for (int i=head[u];i!=-1;i=next[i])
    40     {
    41         int v=rea[i],fee=val[i];
    42         if (v==fa||vis[v]) continue;
    43         dis[v]=(dis[u]+fee)%3;
    44         get_dis(v,u);
    45     }
    46 }
    47 int calc(int u,int now)
    48 {
    49     num[0]=num[1]=num[2]=0;
    50     dis[u]=now;get_dis(u,-1);
    51     return num[1]*num[2]*2+num[0]*num[0];
    52 }
    53 void solve(int u)
    54 {
    55     ans+=calc(u,0);
    56     vis[u]=1;
    57     for (int i=head[u];i!=-1;i=next[i])
    58     {
    59         int v=rea[i],fee=val[i];
    60         if (vis[v]) continue;
    61         ans-=calc(v,fee);
    62         total=siz[v];
    63         id=0;
    64         get_heart(v,-1);
    65         solve(id);
    66     }
    67 }
    68 int gcd(int a,int b)
    69 {
    70     return b?gcd(b,a%b):a;
    71 }
    72 int main()
    73 {
    74     scanf("%d",&n);
    75     ans=cnt=id=0;
    76     memset(vis,0,sizeof(vis));
    77     memset(head,-1,sizeof(head));
    78     for (int i=1,x,y,z;i<n;i++)
    79     {
    80         scanf("%d%d%d",&x,&y,&z);
    81         add(x,y,z),add(y,x,z);
    82     }
    83     total=n,f[0]=inf;
    84     get_heart(1,-1);
    85     solve(id);
    86     int ys=gcd(ans,n*n);
    87     printf("%d/%d",ans/ys,n*n/ys);
    88 }
  • 相关阅读:
    23种设计模式
    设计模式中类的关系
    简单工厂模式
    SQL正则表达式
    C#中各种计时器
    C# List 排序
    常见名词解释
    PetaPoco入门
    jQuery UI Dialog
    c# winform 获取当前程序运行根目录
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/7766547.html
Copyright © 2011-2022 走看看