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 }

     

  • 相关阅读:
    December 23rd 2016 Week 52nd Friday
    December 22nd 2016 Week 52nd Thursday
    December 21st 2016 Week 52nd Wednesday
    December 20th 2016 Week 52nd Tuesday
    December 19th 2016 Week 52nd Sunday
    December 18th 2016 Week 52nd Sunday
    uva294(唯一分解定理)
    uva11624Fire!(bfs)
    fzu2150Fire Game(双起点bfs)
    poj3276Face The Right Way
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/10585006.html
Copyright © 2011-2022 走看看