Processing math: 100%

hdu5449 Robot Dog (树形dp+倍增lca)

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

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

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

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

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

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

那我们能得出f[x]=1k+1+ki=1f[ch[i]]+1k+1+kk+1(1k+1+ki=1f[ch[i]]+1k+1+kk+1(...

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

1k+1+ki=1f[ch[i]]+1k+1记为a,kk+1,就有f[x]=a+b(a+b(a+b(a+b(....=(1+b1+b2+...)a=a1b(等比数列和的极限)

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

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

然后就wa了...

可以发现其实这些期望都是整数,因为11b=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\n",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\n",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\n",ans);
143         }
144         if(T>1) printf("\n");
145     }
146     return 0;
147 }
复制代码

 

posted @   Ressed  阅读(266)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· 现代计算机视觉入门之:什么是视频
阅读排行:
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· .NET Core GC压缩(compact_phase)底层原理浅谈
· Winform-耗时操作导致界面渲染滞后
· Phi小模型开发教程:C#使用本地模型Phi视觉模型分析图像,实现图片分类、搜索等功能
· 语音处理 开源项目 EchoSharp
点击右上角即可分享
微信分享提示