3143: [Hnoi2013]游走 - BZOJ

Description

一个无向连通图,顶点从1编号到N,边从1编号到M。
小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数。当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和。
现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小。

Input

第一行是正整数N和M,分别表示该图的顶点数 和边数,接下来M行每行是整数u,v(1≤u,v≤N),表示顶点u与顶点v之间存在一条边。 输入保证30%的数据满足N≤10,100%的数据满足2≤N≤500且是一个无向简单连通图。

Output

仅包含一个实数,表示最小的期望值,保留3位小数。

Sample Input

3 3

2 3

1 2

1 3

Sample Output

3.333
HINT

边(1,2)编号为1,边(1,3)编号2,边(2,3)编号为3。


经某位大神的讲解,瞬间领悟了,原来这么简单
设点i的期望经过次数为f[i],那么就有f[i]=∑f[j]/d[j](j与i之间有边相连,d[j]为点j关联的边数)
因为一开始在点1上,所以f[1]还要加上一个1
又因为到了n点就结束,所以点n不能为其他点提供期望经过次数,设f[n]=0
所以我们可以列出n-1个方程,一共有n-1个变量,可以解出n-1个点的期望经过次数
然后我们可以求出每条边的期望经过次数
对于每一条边(v,u)它的期望经过次数为f[v]/d[i]+f[u]/d[v]
再排个序,根据排序不等式我们知道,倒序才是最小的,倒着标号,然后求和得到最小期望总分
最开始在BZOJ上过了,Wikioi上没过
我以为是精度太高了,把extended改成了double,还是没过
后来下了标程才知道,原来在判断是否为0时用到了精度判断
在BZOJ上不能用精度判断,在wikioi上必须用精度判断
注意细节啊

 

  1 const
  2     eps=1e-7;
  3 var
  4     n,m:longint;
  5     d:array[0..510]of longint;
  6     f:array[0..510,0..510]of extended;
  7     v,u:array[0..250000]of longint;
  8     exp:array[0..250000]of extended;
  9     ans:extended;
 10 
 11 procedure swap(var x,y:extended);
 12 var
 13     t:extended;
 14 begin
 15     t:=x;
 16     x:=y;
 17     y:=t;
 18 end;
 19 
 20 procedure sort(l,r:longint);
 21 var
 22     i,j:longint;
 23     z:extended;
 24 begin
 25     i:=l;
 26     j:=r;
 27     z:=exp[(l+r)>>1];
 28     repeat
 29       while exp[i]>z do
 30         inc(i);
 31       while exp[j]<z do
 32         dec(j);
 33       if i<=j then
 34       begin
 35         swap(exp[i],exp[j]);
 36         inc(i);
 37         dec(j);
 38       end;
 39     until i>j;
 40     if j>l then sort(l,j);
 41     if i<r then sort(i,r);
 42 end;
 43 
 44 procedure main;
 45 var
 46     i,j,k:longint;
 47     s:extended;
 48 begin
 49     read(n,m);
 50     for i:=1 to m do
 51       begin
 52         read(v[i],u[i]);
 53         inc(d[v[i]]);
 54         inc(d[u[i]]);
 55       end;
 56     for i:=1 to n-1 do
 57       f[i,i]:=-1;
 58     for i:=1 to m do
 59       begin
 60         f[v[i],u[i]]:=f[v[i],u[i]]+1/d[u[i]];
 61         f[u[i],v[i]]:=f[u[i],v[i]]+1/d[v[i]];
 62       end;
 63     f[1,n]:=-1;
 64     for i:=2 to n-1 do
 65       f[i,n]:=0;
 66     for i:=1 to n-2 do
 67       begin
 68         for j:=i to n-1 do
 69           if f[j,i]<>0 then break;
 70         for k:=i to n do
 71           swap(f[i,k],f[j,k]);
 72         for j:=i+1 to n-1 do
 73           if abs(f[j,i])-eps>0 then
 74           begin
 75             s:=f[j,i]/f[i,i];
 76             f[j,i]:=0;
 77             for k:=i+1 to n do
 78               f[j,k]:=f[j,k]-s*f[i,k];
 79           end;
 80       end;
 81     for i:=n-1 downto 1 do
 82       begin
 83         for j:=i+1 to n-1 do
 84           f[i,n]:=f[i,n]-f[j,0]*f[i,j];
 85         f[i,0]:=f[i,n]/f[i,i];
 86       end;
 87     for i:=1 to m do
 88       begin
 89         exp[i]:=exp[i]+f[v[i],0]/d[v[i]];
 90         exp[i]:=exp[i]+f[u[i],0]/d[u[i]];
 91       end;
 92     sort(1,m);
 93     for i:=1 to m do
 94       ans:=ans+i*exp[i];
 95     write(ans:0:3);
 96 end;
 97 
 98 begin
 99     main;
100 end.
View Code

 

posted @ 2014-03-05 14:19  Randolph87  阅读(329)  评论(0编辑  收藏  举报