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 }
  • 相关阅读:
    某个牛人做WINDOWS系统文件详解
    常用ASP脚本程序集锦
    LINUX基础:文件安全与权限
    proftpd+mysql+quota
    apache2.0.49tomcat5.0.19jk2建立virtualHost
    URL Redirection(转) Anny
    顶级域名后缀列表(转) Anny
    \u4E00\u9FA5意义 Anny
    How to POST Form Data Using Ruby(转) Anny
    How to get rid of 'Enter password to unlock your login keyring' in Ubuntu(转) Anny
  • 原文地址:https://www.cnblogs.com/Ressed/p/9748430.html
Copyright © 2011-2022 走看看