zoukankan      html  css  js  c++  java
  • hdu5449 Robot Dog (树形dp+倍增lca)

    (警告:本篇博客包含大量人类本质内容)

    先处理出来lca,然后就只需要知道从每个点到他的父亲、和从他的父亲到这个点的期望时间就可以了

    我们设f[x]为x到他父亲的期望时间;g[x]为从x的父亲到x的期望时间(注意到这两个是不一样的)

    只考虑怎么算f,g是类似的

    从某个点想走到他父亲时,情况会有:直接走到;先走到某个儿子然后走回来,再走到父亲;先走到某个儿子然后走回来,再走到某个儿子然后走回来,再走到某个儿子然后走回来,....,然后走到父亲

    假设x有k个儿子,每个儿子记为ch[1...k]

    那我们能得出$f[x]=frac{1}{k+1}+sumlimits_{i=1}^{k}{frac{f[ch[i]]+1}{k+1}}+frac{k}{k+1}(frac{1}{k+1}+sumlimits_{i=1}^{k}{frac{f[ch[i]]+1}{k+1}}+frac{k}{k+1}(...$

    意思是,有$frac{1}{k+1}$的可能性直接走到,另外$frac{1}{k+1}$先用1时间走错到儿子、然后再用儿子的那个期望时间走回来,并以$frac{k}{k+1}$的可能性再次有$frac{1}{k+1}$的可能性直接走到,另外$frac{1}{k+1}$先用1时间走错到儿子、然后再用儿子的那个期望时间走回来,并以$frac{k}{k+1}$的可能性再次...

    把$frac{1}{k+1}+sumlimits_{i=1}^{k}{frac{f[ch[i]]+1}{k+1}}$记为a,$frac{k}{k+1}$,就有$f[x]=a+b(a+b(a+b(a+b(....=(1+b^1+b^2+...)a=frac{a}{1-b}$(等比数列和的极限)

    这样dfs一下(好几下),就可以算出f了,g同理(注意顺序,两次dfs分别算f和g,算f的时候先算孩子,算g的时候先算父亲),只不过是有可能走错到父亲

    然后倍增记一记f和g的和,做lca就行了(注意路径的方向)

    然后就wa了...

    可以发现其实这些期望都是整数,因为$frac{1}{1-b}=k+1$,而a的分母又都是k+1...所以改用long long,避免掉奇奇怪怪的精度问题,就可以过了..(怀疑是%.4lf是否四舍五入的问题,我的本地是会四舍五入的所以拍不出锅,但要是直接截取就锅了...)

      1 #include<bits/stdc++.h>
      2 #define pa pair<int,int>
      3 #define CLR(a,x) memset(a,x,sizeof(a))
      4 using namespace std;
      5 typedef long long ll;
      6 const int maxn=5e4+10;
      7 
      8 inline ll rd(){
      9     ll x=0;char c=getchar();int neg=1;
     10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
     11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
     12     return x*neg;
     13 }
     14 
     15 int eg[maxn*2][2],egh[maxn],ect;
     16 int N,Q;
     17 ll f[maxn][20],g[maxn][20];
     18 int fa[maxn][20],dep[maxn];
     19 
     20 inline void adeg(int a,int b){
     21     eg[++ect][0]=b;eg[ect][1]=egh[a];egh[a]=ect;
     22 }
     23 
     24 void dfs1(int x){
     25     int k=0;
     26     for(int i=egh[x];i;i=eg[i][1]){
     27         int b=eg[i][0];if(b==fa[x][0]) continue;
     28         dep[b]=dep[x]+1;fa[b][0]=x;
     29         k++;dfs1(b);
     30     }
     31     if(fa[x][0]){
     32         ll alpha=1;
     33         for(int i=egh[x];i;i=eg[i][1]){
     34             int b=eg[i][0];if(b==fa[x][0]) continue;
     35             alpha+=f[b][0]+1;
     36         }
     37         f[x][0]=alpha;
     38     }
     39     
     40 }
     41 
     42 void dfs2(int x){
     43     int k=0;
     44     for(int i=egh[x];i;i=eg[i][1]){
     45         int b=eg[i][0];if(b==fa[x][0]) continue;
     46         k++;
     47     }
     48     if(fa[x][0]){
     49         ll alpha=1;
     50         for(int i=egh[x];i;i=eg[i][1]){
     51             int b=eg[i][0];if(b==fa[x][0]) continue;
     52             alpha+=f[b][0]+1;
     53         }
     54         for(int i=egh[x];i;i=eg[i][1]){
     55             int b=eg[i][0];if(b==fa[x][0]) continue;
     56             ll alphai=alpha-(f[b][0]+1);
     57             alphai+=g[x][0]+1;
     58             g[b][0]=alphai;
     59         }
     60     }else{
     61         ll alpha=1;
     62         for(int i=egh[x];i;i=eg[i][1]){
     63             int b=eg[i][0];if(b==fa[x][0]) continue;
     64             alpha+=f[b][0]+1;
     65         }
     66         for(int i=egh[x];i;i=eg[i][1]){
     67             int b=eg[i][0];if(b==fa[x][0]) continue;
     68             double alphai=alpha-(f[b][0]+1);
     69             g[b][0]=alphai;
     70         }
     71     }
     72     for(int i=egh[x];i;i=eg[i][1]){
     73         int b=eg[i][0];if(b==fa[x][0]) continue;
     74         dfs2(b);
     75     }
     76 //    printf("%d %lf %lf
    ",x,f[x][0],g[x][0]);
     77 }
     78 
     79 void getst(int x){
     80     for(int i=0;fa[x][i]&&fa[fa[x][i]][i];i++){
     81         fa[x][i+1]=fa[fa[x][i]][i];
     82         f[x][i+1]=f[x][i]+f[fa[x][i]][i];
     83         g[x][i+1]=g[x][i]+g[fa[x][i]][i];
     84 //        printf("%d %d %d %lf %lf
    ",x,i+1,fa[x][i+1],f[x][i+1],g[x][i+1]);
     85     }
     86     for(int i=egh[x];i;i=eg[i][1]){
     87         int b=eg[i][0];if(b==fa[x][0]) continue;
     88         getst(b);
     89     }
     90 }
     91 
     92 inline ll solve(int s,int t){
     93     ll re=0;
     94     if(dep[s]>dep[t]){
     95         for(int i=18;i>=0;i--){
     96             if(fa[s][i]&&dep[fa[s][i]]>=dep[t]){
     97                 re+=f[s][i],s=fa[s][i];
     98             }
     99         }
    100 //        if(s==t) return re-f[s][0];
    101     }else if(dep[t]>dep[s]){
    102         for(int i=18;i>=0;i--){
    103             if(fa[t][i]&&dep[fa[t][i]]>=dep[s]){
    104                 re+=g[t][i],t=fa[t][i];
    105             }
    106         }
    107 //        if(s==t) return re-g[t][0];
    108     }
    109     if(s==t) return re;
    110     for(int i=18;i>=0;i--){
    111         if(fa[s][i]&&fa[t][i]&&fa[s][i]!=fa[t][i]){
    112             re+=f[s][i]+g[t][i];
    113             s=fa[s][i],t=fa[t][i];
    114         }
    115     }re+=f[s][0]+g[t][0];
    116     return re;
    117 }
    118 
    119 int main(){
    120     // freopen("5449.in","r",stdin);
    121     // freopen("5449.out","w",stdout);
    122     int i,j,k;
    123     for(int T=rd();T;T--){
    124         CLR(fa,0);CLR(dep,0);CLR(egh,0);ect=0;
    125         CLR(f,0);CLR(g,0);
    126         N=rd();
    127         for(i=1;i<N;i++){
    128             int a=rd()+1,b=rd()+1;
    129             adeg(a,b);adeg(b,a);
    130         }
    131         dep[1]=1;dfs1(1);dfs2(1);
    132         getst(1);
    133         Q=rd();
    134         for(i=1;i<=Q;i++){
    135             int p=rd(),lst=rd()+1;
    136             ll ans=0;
    137             for(j=1;j<=p;j++){
    138                 int now=rd()+1;
    139                 ans+=solve(lst,now);
    140                 lst=now;
    141             }
    142             printf("%lld.0000
    ",ans);
    143         }
    144         if(T>1) printf("
    ");
    145     }
    146     return 0;
    147 }
  • 相关阅读:
    [网络技术][转]网卡的offload概念
    [网络技术][转]路由表查找过程(ip_route_input_slow)
    [linux-内核][转]内核日志及printk结构浅析
    [DPDK][转]DPDK编程开发(4)—lcore
    [技术新闻]相关网站
    [计算机、网络相关历史]unix简史
    [编辑器]sublime使用入门
    [CDN]CDN的系统架构
    [windows操作系统]windows管理
    [安卓]创建一个视图类
  • 原文地址:https://www.cnblogs.com/Ressed/p/9748430.html
Copyright © 2011-2022 走看看