zoukankan      html  css  js  c++  java
  • 题解:luogu P2634 [国家集训队]聪聪可可

    题目描述

    聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃、两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已经玩儿腻了这种低智商的游戏。

    他们的爸爸快被他们的争吵烦死了,所以他发明了一个新游戏:由爸爸在纸上画n个“点”,并用n-1条“边”把这n个“点”恰好连通(其实这就是一棵树)。并且每条“边”上都有一个数。接下来由聪聪和可可分别随即选一个点(当然他们选点时是看不到这棵树的),如果两个点之间所有边上数的和加起来恰好是3的倍数,则判聪聪赢,否则可可赢。

    聪聪非常爱思考问题,在每次游戏后都会仔细研究这棵树,希望知道对于这张图自己的获胜概率是多少。现请你帮忙求出这个值以验证聪聪的答案是否正确。

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1: 
    5
    1 2 1
    1 3 2
    1 4 1
    2 5 3
    输出样例#1: 
    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。

    题解:

    点分板题,但处理每层暴力n^2两两组合的话会T。

    考虑将每个数按模3后的结果分类。显然,若两条权为w1,w2的路径组合后为三的倍数,那么只有三种情况:w1%3=0,w2%3=0或w1%3=1,w2%3=2或w1%3=2,w2%3=1。

    这样问题就很简单了:处理每层时,统计模3为1,2,0的路径有多少条,然后直接算就好了,这样单层就可以做到O(n)了

    代码如下:

    #include<bits/stdc++.h>
    #define MAXN 40005
    #define INF 1e9
    using namespace std;
    struct front_star{
        int to,next,w;
    }edge[MAXN];
    int n,cnt=0,k,mx,root,ans=0,tot=1,siz;
    int head[MAXN],sz[MAXN],temp[MAXN],idx[MAXN];
    bool vis[MAXN];
    int maxn(int a,int b)
    {
        return a>b?a:b;
    }
    int Euclid_GCD(int a, int b) 
    {
        return b?Euclid_GCD(b, a%b):a;
    }
    void addedge(int u,int v,int c)
    {
        cnt++;
        edge[cnt].to=v;
        edge[cnt].w=c;
        edge[cnt].next=head[u];
        head[u]=cnt;
    }
    void findroot(int u,int fa)
    {
        sz[u]=1;
        int msz=0;
        for(int i=head[u];~i;i=edge[i].next)
            {
                int v=edge[i].to;
                if(v!=fa&&!vis[v])
                   {
                         findroot(v,u); 
                         sz[u]+=sz[v];
                      msz=maxn(msz,sz[v]);       
                   }
            }
        msz=maxn(msz,siz-sz[u]);
        if(msz<mx)
           {
                  mx=msz;
                  root=u;
           }       
    }
    void init()
    {
        memset(vis,false,sizeof(vis));
        memset(head,-1,sizeof(head));
        scanf("%d",&n);
        for(int i=1;i<=n-1;i++)
            {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                addedge(a,b,c);
                addedge(b,a,c);
            }
        siz=n;
        mx=INF;
        findroot(1,1);
    }
    void dist(int u,int fa)
    {
        for(int i=head[u];~i;i=edge[i].next)
            {
                int v=edge[i].to;
                if(!vis[v]&&v!=fa)
                   {
                          tot++;
                          idx[v]=tot;
                          temp[tot]=temp[idx[u]]+edge[i].w;
                          dist(v,u);
                   }
            }
    }
    int count_ans(int u,int val)
    {
        tot=1;
        idx[u]=1;
        temp[1]=val;
        dist(u,u);
        int s1=0,s2=0,s3=0;
        for(int i=1;i<=tot;i++)
            {
                if(temp[i]%3==0)
                   s3++;
                if(temp[i]%3==1)
                   s1++;
                if(temp[i]%3==2)
                   s2++;      
            }
        int ret=s3*s3+2*s1*s2-s3;    
        return ret;          
    }
    void divide(int u)
    {
        ans+=count_ans(u,0);
        vis[u]=true;
        for(int i=head[u];~i;i=edge[i].next)
            {
                int v=edge[i].to;
                if(!vis[v])
                   {
                           ans-=count_ans(v,edge[i].w);
                           siz=sz[v];
                           mx=INF;
                           findroot(v,u);
                        divide(root);  
                   }
            }
    }
    int main()
    {
        init();
        divide(root);
        int GCD=Euclid_GCD(ans+n,n*n);
        printf("%d/%d
    ",(ans+n)/GCD,n*n/GCD);
        return 0;
    }
    View Code
  • 相关阅读:
    时间差的计算
    时间差的计算第二篇
    并不能完全不编码完成Windows Service的安装和卸载
    今年是搜索引擎年吗?热!搜索引擎算法点击率火爆
    Virtual PC,我真的不敢用你!
    我理解的17种C#写的Hello World程序
    反搜索引擎
    如何保证Windows Serverice健壮长效运转?
    服务器是怎么做成的?
    超酷的超级DataGrid
  • 原文地址:https://www.cnblogs.com/nanjolno/p/9028288.html
Copyright © 2011-2022 走看看