zoukankan      html  css  js  c++  java
  • BZOJ 2152: 聪聪可可 点分治

    2152: 聪聪可可

    Time Limit: 20 Sec

    Memory Limit: 256 MB

    题目连接

    http://www.lydsy.com/JudgeOnline/problem.php?id=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

    HINT

    题意

    给你一棵树,问你有多少对点,使得这些点之间的距离是3的倍数

    题解:

    很显然的点分治,首先转化为有根树,然后开始处理就行

    边权我们可以直接%3就好了

    来自不同子树的,减去来自相同子树,这就是答案(这句话很关键

    代码:

    #include<iostream>
    #include<stdio.h>
    #include<vector>
    using namespace std;
    #define maxn 1000005
    struct node
    {
        int v,w;
    };
    vector<node>E[maxn];
    int n,ans;
    int f[maxn],sum,vis[maxn],root;
    int t0,t1,t2,son[maxn];
    int d[maxn];
    int gcd(int a,int b)
    {
        if(b==0)return a;
        return gcd(b,a%b);
    }
    void getroot(int x,int fa)
    {
        son[x]=1,f[x]=0;
        for(int i=0;i<E[x].size();i++)
        {
            node p = E[x][i];
            if(vis[p.v]||p.v==fa)continue;
            getroot(p.v,x);
            son[x]+=son[p.v];
            f[x]=max(f[x],son[p.v]);
        }
        f[x]=max(f[x],sum-son[x]);
        if(f[x]<f[root])root=x;
    }
    void dfs(int x,int fa)
    {
        if(d[x]==0)t0++;
        if(d[x]==1)t1++;
        if(d[x]==2)t2++;
        for(int i=0;i<E[x].size();i++)
        {
            node p = E[x][i];
            if(vis[p.v])continue;
            if(p.v==fa)continue;
            d[p.v]=(d[x]+p.w)%3;
            dfs(p.v,x);
        }
    }
    int cal(int x,int val)
    {
        t0=t1=t2=0;
        d[x]=val;
        dfs(x,0);
        return t0*t0+t1*t2*2;
    }
    void work(int x)
    {
        ans+=cal(x,0);
        vis[x]=1;
        for(int i=0;i<E[x].size();i++)
        {
            node p = E[x][i];
            if(vis[p.v])continue;
            ans-=cal(p.v,p.w);
            root=0,sum=son[p.v];
            getroot(p.v,0);
            work(root);
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            int x,y,z;scanf("%d%d%d",&x,&y,&z);
            z = z%3;
            node p;
            p.v = y,p.w = z;
            E[x].push_back(p);
            p.v = x;
            E[y].push_back(p);
        }
        f[0]=sum=n;
        getroot(1,0);
        work(1);
        int p = gcd(ans,n*n);
        printf("%d/%d
    ",ans/p,n*n/p);
    }
  • 相关阅读:
    树链剖分 (模板) 洛谷3384
    ST表 (模板) 洛谷3865
    IOI 2005 River (洛谷 3354)
    IOI 2005 River (洛谷 3354)
    poj1094 Sorting It All Out
    poj1094 Sorting It All Out
    spfa(模板)
    HAOI 2006 受欢迎的牛 (洛谷2341)
    HAOI 2006 受欢迎的牛 (洛谷2341)
    洛谷1850(NOIp2016) 换教室——期望dp
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5019767.html
Copyright © 2011-2022 走看看