zoukankan      html  css  js  c++  java
  • P2634 [国家集训队]聪聪可可(树形dp)

    题目描述

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

    他们的爸爸快被他们的争吵烦死了,所以他发明了一个新游戏:由爸爸在纸上画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。




     

    说是点分治的模板,???,什么是点分治?

    容易发现是dp

    f i j  表示到i点的距离在模3意义下为j的路径数 f i 0 等于;

    转移的时候模就完事了

    统计答案时需要在转移某一个子树前进行统计。其实就是一个卷积,说白了就是让 前面的子树的点到点x的距离 与 当前子树中的点到点x的距离 在模3意义下为0。因为点对有序,所以乘2。

    。最后答案加上 每个点到本身的方案书(其实就是n) , 去和n*n取gcd即可。





     

     1 #include "bits/stdc++.h"
     2 
     3 using namespace std;
     4 typedef long long ll;
     5 struct aa
     6 {
     7     
     8     int so,v;
     9 };
    10 
    11 ll f[30000][4];
    12 vector<aa> v[200000];
    13 ll ans=0;
    14 
    15 void dfs(int x,int fa)
    16 {
    17      f[x][0]=1;
    18     
    19     for (auto i:v[x])
    20     {
    21         int so=i.so; int v=i.v;
    22         if(so==fa)continue;
    23         dfs(so,x);
    24         for(int k=0;k<=2;k++){
    25             int t=(k+v)%3;
    26             if(!t)ans+=2*f[so][k]*f[x][0];
    27             else if(t==1)ans+=2*f[so][k]*(f[x][2]);
    28             else ans+=f[so][k]*f[x][1]*2;
    29             
    30         } 
    31         
    32        for (int k=0;k<=2;k++)
    33        {
    34             f[x][(v+k)%3]+=f[so][k];
    35        }
    36       
    37     }
    38     
    39 }
    40 
    41 int main()
    42 {
    43    int n;cin>>n;
    44    for (int i=1;i<n;i++)
    45    {
    46         int l,r,val;cin>>l>>r>>val;
    47         v[l].push_back({r,val});
    48         v[r].push_back({l,val}); 
    49    }
    50    
    51    dfs(1,-1);
    52   
    53  ans+=n; int gcd=__gcd(ans,1ll*n*n);
    54  cout<<ans/gcd<<"/"<<n*n/gcd; 
    55   //cout<<ans;
    56 }

     

  • 相关阅读:
    各种经典透镜投影模型
    表达式和运算
    数组
    如何使用布尔类型
    如何使用数字类型
    如何使用字符串类型
    如何声明变量,如何给变量赋值
    变量 构造函数 New 关键字
    调用write方法打印语句到浏览器
    MVC中几种常用ActionResult
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/10585006.html
Copyright © 2011-2022 走看看