2878: [Noi2012]迷失游乐园 - BZOJ

Description

放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩。进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点、m条道路的无向连通图,且该图中至多有一个环(即m只可能等于n或者n-1)。小Z现在所在的大门也正好是一个景点。小Z不知道什么好玩,于是他决定,从当前位置出发,每次随机去一个和当前景点有道路相连的景点,并且同一个景点不去两次(包括起始景点)。贪玩的小Z会一直游玩,直到当前景点的相邻景点都已经访问过为止。小Z所有经过的景点按顺序构成一条非重复路径,他想知道这条路径的期望长度是多少?小Z把游乐园的抽象地图画下来带回了家,可是忘了标哪个点是大门,他只好假设每个景点都可能是大门(即每个景点作为起始点的概率是一样的)。同时,他每次在选择下一个景点时会等概率地随机选择一个还没去过的相邻景点。
Input


第一行是两个整数n和m,分别表示景点数和道路数。 接下来行,每行三个整数Xi, Yi, Wi,分别表示第i条路径的两个景点为Xi, Yi,路径长Wi。所有景点的编号从1至n,两个景点之间至多只有一条道路。
Output

 共一行,包含一个实数,即路径的期望长度。
Sample Input
4 3
1 2 3
2 3 1
3 4 4
Sample Output
6.00000000

【样例解释】样例数据中共有6条不同的路径: 路径 长度 概率
1-->4 8 1/4
2-->1 3 1/8
2-->4 5 1/8
3-->1 4 1/8
3-->4 4 1/8
4-->1 8 1/4
因此期望长度 = 8/4 + 3/8 + 5/8 + 4/8 + 4/8 + 8/4 = 6.00
【评分方法】本题没有部分分,你程序的输出只有和标准答案的差距不超过0.01时,才能获得该测试点的满分,否则不得分。
【数据规模和约定】对于100%的数据,1 <= Wi <= 100。 测试点编号 n m 备注
1 n=10 m = n-1 保证图是链状
2 n=100 只有节点1的度数大于2
3 n=1000 /
4 n=100000 /
5 n=100000 /
6 n=10 m = n /
7 n=100 环中节点个数<=5
8 n=1000 环中节点个数<=10
9 n=100000 环中节点个数<=15
10 n=100000 环中节点个数<=20

 

一直WA,最后才发现环没仔细考虑,因为最后一个是不可能走到i的所以度数减1

就是求一个down和一个up,分别表示向下走的期望长度和向上走的期望长度

对于环,我们以每个环上的节点为根求一边down

然后枚举环上的点更新up值,环上点的up值就表示第一条边走环边的期望长度

然后用环上节点的up值更新其他点的up值

  1 const
  2     maxn=100100;
  3 var
  4     first,d,fa:array[0..maxn]of longint;
  5     up,down:array[0..maxn]of double;
  6     vis,cir:array[0..maxn]of boolean;
  7     last,next,w:array[0..maxn*2]of longint;
  8     huan,len:array[0..maxn]of longint;
  9     n,m,tot,cnt:longint;
 10     ans:double;
 11     flag:boolean;
 12  
 13 procedure insert(x,y,z:longint);
 14 begin
 15     inc(tot);
 16     last[tot]:=y;
 17     next[tot]:=first[x];
 18     first[x]:=tot;
 19     w[tot]:=z;
 20     inc(d[y]);
 21 end;
 22  
 23 procedure dfs(x:longint);
 24 var
 25     i,j:longint;
 26 begin
 27     vis[x]:=true;
 28     i:=first[x];
 29     while i<>0 do
 30         begin
 31             if flag then exit;
 32             if (vis[last[i]])and(fa[x]<>last[i]) then
 33             begin
 34                 len[last[i]]:=w[i];
 35                 j:=x;
 36                 while j<>fa[last[i]] do
 37                     begin
 38                         inc(cnt);cir[j]:=true;
 39                         huan[cnt]:=j;
 40                         j:=fa[j];
 41                     end;
 42                 flag:=true;exit;
 43             end;
 44             if not vis[last[i]] then
 45             begin
 46                 fa[last[i]]:=x;len[last[i]]:=w[i];
 47                 dfs(last[i]);
 48             end;
 49             i:=next[i];
 50         end;
 51 end;
 52  
 53 procedure dfs1(x:longint);
 54 var
 55     i:longint;
 56 begin
 57     vis[x]:=true;
 58     i:=first[x];
 59     while i<>0 do
 60         begin
 61             if not vis[last[i]] then
 62             begin
 63                 dfs1(last[i]);
 64                 down[x]:=down[x]+w[i]+down[last[i]]/(d[last[i]]-1+longint(d[last[i]]=1));
 65             end;
 66             i:=next[i];
 67         end;
 68 end;
 69  
 70 procedure dfs2(x:longint);
 71 var
 72     i:longint;
 73 begin
 74     if (not cir[x]) and (fa[x]<>0) then up[x]:=len[x]+(up[fa[x]]+down[fa[x]]-len[x]-down[x]/(d[x]-1+longint(d[x]=1)))/(d[fa[x]]-1+longint(d[fa[x]]=1));
 75     vis[x]:=true;
 76     i:=first[x];
 77     while i<>0 do
 78         begin
 79             if not vis[last[i]] then
 80             begin
 81                 fa[last[i]]:=x;len[last[i]]:=w[i];
 82                 dfs2(last[i]);
 83             end;
 84             i:=next[i];
 85         end;
 86 end;
 87  
 88 procedure main;
 89 var
 90     i,x,y,z:longint;
 91     s:double;
 92 begin
 93     read(n,m);cnt:=-1;
 94     for i:=1 to m do
 95         begin
 96             read(x,y,z);
 97             insert(x,y,z);
 98             insert(y,x,z);
 99         end;
100     if m=n-1 then
101         begin
102             dfs1(1);
103             for i:=1 to n do vis[i]:=false;
104             dfs2(1);
105             for i:=1 to n do ans:=ans+(up[i]+down[i])/d[i];
106         end
107     else
108         begin
109             dfs(1);
110             for i:=1 to n do vis[i]:=false;
111             for i:=0 to cnt do vis[huan[i]]:=true;
112             for i:=0 to cnt do dfs1(huan[i]);
113             for i:=0 to cnt do
114                 begin
115                     x:=(i+1)mod(cnt+1);s:=1;
116                     while x<>i do
117                         begin
118                             if (x+1)mod(cnt+1)=i then up[huan[i]]:=up[huan[i]]+s*len[huan[(x+cnt)mod(cnt+1)]]+s*down[huan[x]]/(d[huan[x]]-2+longint(d[huan[x]]=2))
119                             else up[huan[i]]:=up[huan[i]]+s*len[huan[(x+cnt)mod(cnt+1)]]+s*down[huan[x]]/(d[huan[x]]-1);
120                             s:=s/(d[huan[x]]-1);
121                             x:=(x+1)mod(cnt+1);
122                         end;
123                     x:=(i+cnt)mod(cnt+1);s:=1;
124                     while x<>i do
125                         begin
126                             if (x+cnt)mod(cnt+1)=i then up[huan[i]]:=up[huan[i]]+s*len[huan[x]]+s*down[huan[x]]/(d[huan[x]]-2+longint(d[huan[x]]=2))
127                             else up[huan[i]]:=up[huan[i]]+s*len[huan[x]]+s*down[huan[x]]/(d[huan[x]]-1);
128                             s:=s/(d[huan[x]]-1);
129                             x:=(x+cnt)mod(cnt+1);
130                         end;
131                 end;
132             for i:=1 to n do vis[i]:=false;
133             for i:=0 to cnt do vis[huan[i]]:=true;
134             for i:=0 to cnt do dfs2(huan[i]);
135             for i:=1 to n do ans:=ans+(up[i]+down[i])/d[i];
136         end;
137     writeln(ans/n:0:5);
138 end;
139  
140 begin
141     main;
142 end.
View Code

 

posted @ 2014-06-21 19:37  Randolph87  阅读(557)  评论(0编辑  收藏  举报