然而我并不会做……

  题解戳这里:http://blog.csdn.net/u011265346/article/details/46328543

  好吧先考虑一个简单点的,当m=n-1时,整个是一个树形的结构,无根树我们一般还是转成有根树来处理……然后既然是无法回头的,那么我们可以定一下方向:向下或者向上(废话)

  定义一下:

  son[x]为x的儿子的数量

  down[x]表示从x这个点出发,向叶子们走的期望长度。

  怎么算呢?其实就是所有可能的情况(所有的儿子)加起来,再求个平均,所以我们有$$down[x]=\frac{\sum (down[y]+len(x->y))}{son[x]}$$

  up[x]表示从x这个点出发,经过父亲,走到某个叶子的期望长度。

  这个看上去好难算啊……怎么算呢?我们先算出来每个结点的down[x],然后从上往下DP,这里我们需要考虑的是x的父亲 f ,我们从x向上走到他父亲 f 后(len(x->f)),可以向 f 其他的儿子走,这种方案的期望长度之和为$$ son[f]*down[f]-down[x]-len(f->x) $$如果是继续向上,这种方案的期望长度为$up[f]$,所以有$$up[x]=len(x->f) + \frac{ son[f]*down[f]-down[x]-len(f->x) + up[f]}{son[f]-1+1}$$这里son[f]-1表示是向其他儿子走,+1表示的是继续向上,这么多种方案的概率是相等的。

  那么答案怎么算?当然是$$ans=\sum_{i=1}^n \frac{down[i]*son[i]+up[i]}{son[i]+1} $$

  好的到这里我们就解决了树上的问题,那么环套树其实就是需要特殊处理一下 环上的结点以及与环直接相连的结点,怎么做呢?

  肯定是要先找环的啦= =那么我们dfs搞搞找出环上所有结点,题目限制这样的结点不多,就20个= =

  有一个东西是跟树的情况一样的,那就是从环上某个结点直接向与它相连的外向树上走的期望长度,也就是所有的down[cir[i]],这里cir[i]表示环上的点。

  算出down[cir[i]]以后,跟据刚刚的经验,我们就可以用down来算up啦!同样是从上往下算up的值,只不过这里的“树根”变成了一个环,环上的点的up值其实就是沿着环走到其他的任意一个环上的点,然后再向下走的期望长度啦,举个例子吧:(其实这一段看代码比较好……)

  环上的点编号为1、2、3、4、5,那么对于1来说,顺时针走的话,走到2的概率为1,走到3的概率为$\frac{1}{son[2]+1}$,走到4的话就再乘$\frac{1}{son[3]+1}$……逆时针走的话同理。

  同时我们沿着环每走到一个位置就加上从这里向外向树走的期望长度(注意绕一圈走到头的地方与之前的不一样,因为出发点不可能经过两次)。

  表达式比较难写……好吧其实是我懒,而且长得并不好看,还是看代码比较好:

 1 F(i,1,tot){
 2     int x=cir[i];
 3     double k=1;
 4     for(int j=nex[x];j!=x;j=nex[j]){
 5         if (nex[j]!=x)
 6             up[x]+=k*(len[hash[pre[j]]][hash[j]]+down[j]*son[j]/(son[j]+1));
 7         else
 8             up[x]+=k*(len[hash[pre[j]]][hash[j]]+down[j]);
 9         k/=(son[j]+1);
10     }
11     k=1;
12     for(int j=pre[x];j!=x;j=pre[j]){
13         if (pre[j]!=x)
14             up[x]+=k*(len[hash[nex[j]]][hash[j]]+down[j]*son[j]/(son[j]+1));
15         else 
16             up[x]+=k*(len[hash[nex[j]]][hash[j]]+down[j]);
17         k/=(son[j]+1);    
18     }
19     up[x]/=2;
20 }
View Code

相关文章: