zoukankan      html  css  js  c++  java
  • JZOJ 4225. 【五校联考3day1】宝藏(树上随机游走)

    JZOJ 4225. 【五校联考3day1】宝藏

    题目

    Description

    在这里插入图片描述

    Input

    在这里插入图片描述

    Output

    在这里插入图片描述

    Sample Input

    2
    3
    1 0
    1 2
    2
    1 0 1
    2 0 2 1
    4
    0 1
    2 0
    3 0
    1
    3 0 1 0 1

    Sample Output

    1.0000
    5.0000
    <空行>
    11.0000

    Data Constraint

    在这里插入图片描述

    题解

    • 这是一个树上随机游走的问题。

    • 题目可以简化为:从一个节点出发,等概率地向它所连的点走去,每条边权均为 1 1 1。求从起点按顺序经过的一系列节点后到达终点的期望路径长度。

    • 首先我们把问题中的路线拆分为以下两种:

    • 1、 F ( x ) F(x) F(x)表示从 x x x走向 f a t h e r [ x ] father[x] father[x],记录 f [ x ] f[x] f[x]表示其期望路径长度;

    • 2、 G ( x ) G(x) G(x)表示从 f a t h e r [ x ] father[x] father[x]走向 x x x,记录 g [ x ] g[x] g[x]表示其期望路径长度。

    • 问题中的路径就是若干条上面两种的路径总和,总的期望值也就是每一段的期望值总和。

    • 现在考虑怎么计算 f [ x ] f[x] f[x] g [ x ] g[x] g[x]

    • 先令 d e g [ x ] deg[x] deg[x]表示 x x x的度数, s o n [ x ] son[x] son[x]表示 x x x的子节点集合。

    • 计算 f [ x ] f[x] f[x]的方程如下:
    • 可以直接走到 f a t h e r [ x ] father[x] father[x],也可以经过它的儿子再走到 f a t h e r [ x ] father[x] father[x]
      f [ x ] = 1 + ∑ v ∈ s o n [ x ] f [ v ] + f [ x ] + 1 d e g [ x ] f[x]=frac{1+displaystyle sum _{vin son[x]}f[v]+f[x]+1}{deg[x]} f[x]=deg[x]1+vson[x]f[v]+f[x]+1
      < = > f [ x ] ∗ d e g [ x ] = 1 + ∑ v ∈ s o n [ x ] f [ v ] + f [ x ] + 1 <=>f[x]*deg[x]=1+displaystyle sum _{vin son[x]}f[v]+f[x]+1 <=>f[x]deg[x]=1+vson[x]f[v]+f[x]+1
      < = > f [ x ] ∗ d e g [ x ] = d e g [ x ] + ( d e g [ x ] − 1 ) ∗ f [ x ] + ∑ v ∈ s o n [ x ] f [ v ] <=>f[x]*deg[x]=deg[x]+(deg[x]-1)*f[x]+displaystyle sum _{vin son[x]}f[v] <=>f[x]deg[x]=deg[x]+(deg[x]1)f[x]+vson[x]f[v]
      < = > f [ x ] = d e g [ x ] + ∑ v ∈ s o n [ x ] f [ v ] <=>f[x]=deg[x]+displaystyle sum _{vin son[x]}f[v] <=>f[x]=deg[x]+vson[x]f[v]

    • 计算 g [ x ] g[x] g[x]的方程如下:
    • 可以直接走到 x x x,也可以先走到 f a t h e r [ f a t h e r [ x ] ] father[father[x]] father[father[x]],也可能走到 x x x的兄弟。
      g [ x ] = 1 + ( 1 + g [ x ] + g [ f a t h e r [ x ] ] ) + ∑ v ∈ s o n [ f a t h e r [ x ] ] ∩ v ≠ x f [ v ] + g [ x ] + 1 d e g [ f a t h e r [ x ] ] g[x]=frac{1+(1+g[x]+g[father[x]])+displaystyle sum _{{vin son[father[x]]}∩{v≠x}}f[v]+g[x]+1}{deg[father[x]]} g[x]=deg[father[x]]1+(1+g[x]+g[father[x]])+vson[father[x]]v=xf[v]+g[x]+1
      < = > g [ x ] ∗ d e g [ f a t h e r [ x ] ] = 2 + g [ x ] + g [ f a t h e r [ x ] ] + ∑ v ∈ s o n [ f a t h e r [ x ] ] ∩ v ≠ x f [ v ] + g [ x ] + 1 <=>g[x]*deg[father[x]]=2+g[x]+g[father[x]]+displaystyle sum _{{vin son[father[x]]}∩{v≠x}}f[v]+g[x]+1 <=>g[x]deg[father[x]]=2+g[x]+g[father[x]]+vson[father[x]]v=xf[v]+g[x]+1
      < = > g [ x ] ∗ d e g [ f a t h e r [ x ] ] = d e g [ f a t h e r [ x ] ] + g [ x ] ∗ ( d e g [ f a t h e r [ x ] ] − 1 ) <=>g[x]*deg[father[x]]=deg[father[x]]+g[x]*(deg[father[x]]-1) <=>g[x]deg[father[x]]=deg[father[x]]+g[x](deg[father[x]]1)
      + g [ f a t h e r [ x ] ] + ∑ v ∈ s o n [ f a t h e r [ x ] ] ∩ v ≠ x f [ v ] +g[father[x]]+displaystyle sum _{{vin son[father[x]]}∩{v≠x}}f[v] +g[father[x]]+vson[father[x]]v=xf[v]
      < = > g [ x ] = d e g [ f a t h e r [ x ] ] + g [ f a t h e r [ x ] ] + ∑ v ∈ s o n [ f a t h e r [ x ] ] ∩ v ≠ x f [ v ] <=>g[x]=deg[father[x]]+g[father[x]]+displaystyle sum _{{vin son[father[x]]}∩{v≠x}}f[v] <=>g[x]=deg[father[x]]+g[father[x]]+vson[father[x]]v=xf[v]

    • 于是这样就可以把所有的 f [ x ] f[x] f[x] g [ x ] g[x] g[x]计算出来了。

    • 记得其中 f [ x ] = g [ x ] = 0 f[x]=g[x]=0 f[x]=g[x]=0.

    • 如果一步一步地走,会时间超限,

    • 自然想到用倍增 L C A LCA LCA.

    代码

    #include<cstdio>
    #include<cstring>
    using namespace std;
    int last[50010],next[100010],tov[100010],len=0;
    int deep[50010],deg[50010];
    int f[50010],g[50010],e[17],tn;
    struct node
    {
    	int f,g,to;
    }q[50010][17];
    void add(int x,int y)
    {
    	tov[++len]=y;
    	next[len]=last[x];
    	last[x]=len;
    }
    void dfs(int x,int fa)
    {
    	f[x]=deg[x];
    	for(int i=last[x];i;i=next[i]) if(tov[i]!=fa)
    	{
    		deep[tov[i]]=deep[x]+1;
    		dfs(tov[i],x);
    		f[x]+=f[tov[i]];
    	}
    }
    void dfs1(int x,int sum,int fa)
    {
    	if(x>1) g[x]=g[fa]+deg[fa]+sum-f[x];
    	int ss=0;
    	for(int i=last[x];i;i=next[i]) if(tov[i]!=fa) ss+=f[tov[i]];
    	for(int i=last[x];i;i=next[i]) if(tov[i]!=fa) dfs1(tov[i],ss,x);
    }
    void dfs2(int x,int fa)
    {
    	q[x][0].to=fa,q[x][0].f=f[x],q[x][0].g=g[x];
    	for(int i=1;i<=16;i++) 
    	{
    		q[x][i].to=q[q[x][i-1].to][i-1].to;
    		q[x][i].f=q[x][i-1].f+q[q[x][i-1].to][i-1].f;
    		q[x][i].g=q[x][i-1].g+q[q[x][i-1].to][i-1].g;
    	}
    	for(int i=last[x];i;i=next[i]) if(tov[i]!=fa) dfs2(tov[i],x);
    }
    int main()
    {
    	int n,i,j,k,x,y,qs,p;
    	scanf("%d",&tn);
    	e[0]=1;
    	for(i=1;i<=16;i++) e[i]=e[i-1]*2;
    	while(tn--)
    	{
    		scanf("%d",&n);
    		memset(last,0,sizeof(last));
    		memset(deg,0,sizeof(deg));
    		len=0;
    		for(i=1;i<n;i++)
    		{
    			scanf("%d%d",&x,&y);
    			x++,y++;
    			deg[x]++,deg[y]++;
    			add(x,y);add(y,x);
    		}
    		deep[1]=0;
    		memset(g,0,sizeof(g));
    		memset(f,0,sizeof(f));
    		dfs(1,0);
    		dfs1(1,0,0);
    		dfs2(1,0);
    		scanf("%d",&qs);
    		for(i=1;i<=qs;i++)
    		{
    			scanf("%d",&p);
    			int la,no;
    			scanf("%d",&la);
    			la++;
    			int ans=0;
    			for(j=2;j<=p+1;j++)
    			{
    				scanf("%d",&no);
    				no++;
    				x=la,y=no;
    				if(deep[x]>deep[y])
    				{
    					for(k=16;k>=0;k--) if(deep[x]-e[k]>=deep[y]) 
    					{
    						ans+=q[x][k].f;
    						x=q[x][k].to;
    					}
    				}
    				else
    				{
    					for(k=16;k>=0;k--) if(deep[y]-e[k]>=deep[x])
    					{
    						ans+=q[y][k].g;
    						y=q[y][k].to;
    					}	
    				}
    				if(x!=y)
    				{
    					for(k=16;k>=0;k--) if(q[x][k].to!=q[y][k].to)
    					{
    						ans+=q[x][k].f+q[y][k].g;
    						x=q[x][k].to;
    						y=q[y][k].to;
    					}
    					ans+=q[x][0].f+q[y][0].g;
    				}
    				la=no;
    			}
    			printf("%d.0000
    ",ans);
    		}
    		printf("
    ");
    	}
    	return 0;
    }
    
    哈哈哈哈哈哈哈哈哈哈
  • 相关阅读:
    实变函数资料目录
    高等代数资料目录
    数学分析资料目录
    各大高校数学分析高等代数考研试题参考解答
    高等代数习题集/资料/答案/视频讲解等目录
    数学分析习题集/资料/答案/视频讲解等目录
    数学分析习题集/资料/答案/视频讲解等目录
    Evans 偏微分方程目录
    Berkeley 常微分方程问题集目录
    245道2020年数学分析/91道2020年高等代数考研试题题目分类目录
  • 原文地址:https://www.cnblogs.com/LZA119/p/13910095.html
Copyright © 2011-2022 走看看