bzoj2878

又是环套树dp,这次不是我擅长的类型

首先考虑树上的暴力,肯定是穷举起点然后以起点为根dp

我们用g[i]表示以点i为期望走的路径总长,答案就是1/n*Σ(g[i]/d[i]) (d[i]表示点度数)

不难发现我们只需要两次dfs就能求出g[i],即先求出向下的,然后求向上的

具体的,我们设f[x]表示x向孩子走期望路径长度,这个一次dfs就可以求出来,这时候g[x]求出来的是向孩子走期望路径的总长

再做一次dfs,要加上向上走的路径,可以得到g[y]=g[y]+(g[x]-f[y]-w(x,y))/(d[x]-1)+w(x,y) [fa[y]=x] 注意度数为1的点

那么树就搞定了,环怎么做呢?

还是按照基本思路,把环放到根上,求出环上每个点向下的g[x]

注意到题目给出的条件,环上的点很少,因此我们可以暴力依次计算每个点的g[x]

还是类似上面的思路,并不难,注意细节即可

  1 type node=record
  2        po,next,num:longint;
  3      end;
  4 
  5 var w,u,f,g:array[0..100010] of double;
  6     cir,v:array[0..100010] of boolean;
  7     fp,fa,d,p,b,q,c:array[0..100010] of longint;
  8     e:array[0..200010] of node;
  9     j,i,n,m,len,x,y,z,s,t:longint;
 10     ans:double;
 11 
 12 procedure add(x,y,z:longint);
 13   begin
 14     inc(len);
 15     e[len].po:=y;
 16     e[len].next:=p[x];
 17     e[len].num:=z;
 18     p[x]:=len;
 19     inc(d[x]);
 20   end;
 21 
 22 procedure dfs1(x:longint);
 23   var i,y:longint;
 24   begin
 25     v[x]:=true;
 26     i:=p[x];
 27     while i<>0 do
 28     begin
 29       y:=e[i].po;
 30       if not v[y] and not cir[y] then
 31       begin
 32         dfs1(y);
 33         g[x]:=g[x]+f[y]+e[i].num;
 34       end;
 35       i:=e[i].next;
 36     end;
 37     if d[x]>1 then f[x]:=g[x]/(d[x]-1);
 38   end;
 39 
 40 procedure dfs2(x:longint);
 41   var i,y,k:longint;
 42   begin
 43     v[x]:=true;
 44     i:=p[x];
 45     while i<>0 do
 46     begin
 47       y:=e[i].po;
 48       if not v[y] and not cir[y] then
 49       begin
 50         k:=d[x]-1;
 51         if k=0 then k:=1;
 52         g[y]:=g[y]+(g[x]-f[y]-e[i].num)/k+e[i].num;
 53         dfs2(y);
 54       end;
 55       i:=e[i].next;
 56     end;
 57   end;
 58 
 59 procedure find(x:longint);
 60   var i,y,z:longint;
 61   begin
 62     inc(t);
 63     b[x]:=t;
 64     i:=p[x];
 65     while i<>0 do
 66     begin
 67       y:=e[i].po;
 68       if b[y]=0 then
 69       begin
 70         fa[y]:=x;
 71         fp[y]:=e[i].num;
 72         find(y);
 73       end
 74       else if (y<>fa[x]) and (b[y]<b[x]) then
 75       begin
 76         cir[y]:=true;
 77         z:=x;
 78         inc(s); q[1]:=y;
 79         c[1]:=e[i].num;
 80         while z<>y do
 81         begin
 82           inc(s);
 83           q[s]:=z;
 84           c[s]:=fp[z];
 85           cir[z]:=true;
 86           z:=fa[z];
 87         end;
 88       end;
 89       i:=e[i].next;
 90     end;
 91   end;
 92 
 93 begin
 94   readln(n,m);
 95   for i:=1 to m do
 96   begin
 97     readln(x,y,z);
 98     add(x,y,z);
 99     add(y,x,z);
100   end;
101   if m=n-1 then
102   begin
103     dfs1(1);
104     fillchar(v,sizeof(v),false);
105     dfs2(1);
106   end
107   else begin
108     find(1);
109     fillchar(v,sizeof(v),false);
110     for i:=1 to s do
111     begin
112       x:=q[i];
113       d[x]:=d[x]-2;
114       dfs1(x);
115       q[i+s]:=q[i];
116       c[i+s]:=c[i];
117     end;
118     for i:=1 to s do
119     begin
120       for j:=i+s-1 downto i do
121       begin
122         x:=q[j];
123         if j=i+s-1 then
124         begin
125           z:=d[x];
126           if z=0 then inc(z);
127           u[x]:=g[x]/z;
128         end
129         else begin
130           u[x]:=u[q[j+1]]+c[j];
131           if j<>i then
132             u[x]:=(u[x]+g[x])/(d[x]+1);
133         end;
134       end;
135       for j:=i+1 to i+s do
136       begin
137         x:=q[j];
138         if j<>i+s then u[x]:=0;
139         if j=i+1 then
140         begin
141           z:=d[x];
142           if z=0 then inc(z);
143           u[x]:=g[x]/z;
144         end
145         else begin
146           u[x]:=u[x]+u[q[j-1]]+c[j-1];
147           if j<>i+s then
148             u[x]:=(u[x]+g[x])/(d[x]+1);
149         end;
150       end;
151       w[q[i]]:=u[q[i]];
152     end;
153     fillchar(v,sizeof(v),false);
154     for i:=1 to s do
155     begin
156       x:=q[i];
157       g[x]:=g[x]+w[x];
158       d[x]:=d[x]+2;
159     end;
160     for i:=1 to s do
161       dfs2(q[i]);
162   end;
163   for i:=1 to n do
164     ans:=ans+g[i]/d[i];
165   writeln(ans/n:0:5);
166 end.
View Code

 

转载于:https://www.cnblogs.com/phile/p/4610980.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值