天天看點

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

轉載于:https://www.cnblogs.com/Randolph87/p/3582372.html