CF123E Maze(期望dp,树形dp,式子)

题目链接

题目大意:
给你一棵树,边权都是1,每一个点有一个是起点的概率和一个是终点的概率,你将以起点为根,开始在树上随机dfs,每到一个点,就会将他的所有儿子随机打乱成序列,然后按照那个随机顺序走完,直到走到终点。求dfs从起点到终点的期望长度。

其实一开始看到这个题,还是有点懵逼的啊

根据期望的线性性,我们可以通过求所有相邻点的期望,然后直接相加,得到ans

那我们可以这么考虑,对于一个点来说,假设我们要求的是从 x > y x->y y y x x 的儿子)的期望的话,如果走到一个错的儿子,那么就需要 2 s i z e [ s o n ] 2*size[son] 步重新回来(相当于每条边会走两遍),而每个儿子在对应的 y y 之前的概率又都是 1 2 \frac{1}{2} (所有排列中,要不是y在前,就是那一个在前)

所以可以得知,每一个点的贡献 就是 s i z e [ x ] size[x]

那么我们可以通过枚举终点,然后算其他子树的 s i z e [ x ] size[x] 以及概率和,求出来他们的贡献

最后直接输出ans就好

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define mk makr_pair
#define ll long long

using namespace std;

inline int read()
{
  int x=0,f=1;char ch=getchar();
  while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
  while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
  return x*f;
}

const int maxn = 2e5+1e2;
const int maxm = 2*maxn;

int point[maxn],nxt[maxm],to[maxm];
double val[maxn];
int size[maxn];
double st[maxn],ed[maxn];
int n,m;
double sumst,sumed;
int cnt;
double ans;

void addedge(int x,int y)
{
	nxt[++cnt]=point[x];
	to[cnt]=y;
	point[x]=cnt;
}

void dfs(int x,int fa)
{
	size[x]=1;
	val[x]=st[x];
	//cout<<x<<" "<<val[x]<<endl;
	for (int i=point[x];i;i=nxt[i])
	{
	   int p = to[i];
	   if (p==fa) continue;
	   dfs(p,x);
	   size[x]+=size[p];
	   val[x]+=val[p];
	}
} 
int main()
{
  n=read();
  for (int i=1;i<n;i++)
  {
  	int x=read(),y=read();
  	addedge(x,y);
  	addedge(y,x);
  }
  
  for (int i=1;i<=n;i++)
  {
  	 scanf("%lf%lf",&st[i],&ed[i]);
  	 sumst+=st[i];
  	 sumed+=ed[i];
  }
  
  for(int i=1;i<=n;i++)
  {
  	  st[i]=st[i]/sumst;
  	  ed[i]=ed[i]/sumed;
  	 // printf("%.4lf %.4lf\n",st[i],ed[i]);
  }
  
  dfs(1,0);
  //cout<<val[1]<<endl;
  for (int x=1;x<=n;x++)
  {
  	 for  (int i=point[x];i;i=nxt[i])
  	 {
  	 	int p =to[i];
  	 	if (size[p]>=size[x])
  	 	  ans=ans+1.0*(1.0-val[x])*1.0*(1.0*n-size[x])*ed[x];
		else
		  ans=ans+val[p]*1.0*size[p]*ed[x];
		  
	//	cout<<x<<" "<<p<<" "<<ans<<endl; 
	 }
  } 
  
  printf("%.12lf",ans);
  return 0;
}

猜你喜欢

转载自blog.csdn.net/y752742355/article/details/84557524