之前我们曾经用dp解决过数学期望问题,这次我们用的是解方程的方法
首先在编号之前,肯定要求出每条边的期望经过次数
然后可以转化为求边端点的期望次数
这种做法我一开始接触是noip2013的初赛问题求解,是类似的思想
当出现循环无法用dp解决时,我们考虑列方程
设pi为点i的期望经过次数
则容易得到pi=sigma(pj/dj) dj表示出度,j是与i相邻的点
特殊的p1=1+sigma(pj/dj) pn=0(因为到n就停止了)
于是我们可以得到一个方程组,这样就可以用高斯消元求解
解出之后就能求出边的期望经过次数了,然后贪心分配编号即可
1 var w:array[0..510,0..510] of longint; 2 a:array[0..510,0..510] of double; 3 x,y:array[0..300010] of longint; 4 c,p:array[0..300010] of double; 5 d:array[0..510] of longint; 6 i,j,k,n,m:longint; 7 ans:double; 8 9 procedure swap(var a,b:double); 10 var c:double; 11 begin 12 c:=a; 13 a:=b; 14 b:=c; 15 end; 16 17 procedure calc; 18 var i,j,k,w:longint; 19 begin 20 for i:=1 to n do 21 begin 22 w:=i; 23 for k:=i+1 to n do 24 if abs(a[k,i])>abs(a[w,i]) then w:=k; 25 if w<>i then 26 begin 27 for j:=1 to n+1 do 28 swap(a[w,j],a[i,j]); 29 end; 30 for k:=i+1 to n do 31 for j:=n+1 downto i do 32 a[k,j]:=a[k,j]-a[i,j]*a[k,i]/a[i,i]; 33 end; 34 p[n]:=0; 35 for i:=n-1 downto 1 do 36 begin 37 for j:=i+1 to n do 38 a[i,n+1]:=a[i,n+1]-a[i,j]*p[j]; 39 p[i]:=a[i,n+1]/a[i,i]; 40 end; 41 end; 42 43 procedure sort(l,r: longint); 44 var i,j: longint; 45 x:double; 46 begin 47 i:=l; 48 j:=r; 49 x:=c[(l+r) shr 1]; 50 repeat 51 while c[i]<x do inc(i); 52 while x<c[j] do dec(j); 53 if not(i>j) then 54 begin 55 swap(c[i],c[j]); 56 inc(i); 57 j:=j-1; 58 end; 59 until i>j; 60 if l<j then sort(l,j); 61 if i<r then sort(i,r); 62 end; 63 64 begin 65 readln(n,m); 66 for i:=1 to m do 67 begin 68 readln(x[i],y[i]); 69 inc(d[x[i]]); 70 inc(d[y[i]]); 71 w[x[i],d[x[i]]]:=y[i]; 72 w[y[i],d[y[i]]]:=x[i]; 73 end; 74 a[1,1]:=-1; 75 for i:=1 to d[1] do 76 begin 77 k:=w[1,i]; 78 a[1,k]:=1/d[k]; 79 end; 80 a[1,n+1]:=-1; 81 for i:=2 to n-1 do 82 begin 83 for j:=1 to d[i] do 84 begin 85 k:=w[i,j]; 86 a[i,k]:=1/d[k]; 87 end; 88 a[i,i]:=-1; 89 end; 90 a[n,n]:=1; 91 calc; 92 for i:=1 to m do 93 c[i]:=p[x[i]]/d[x[i]]+p[y[i]]/d[y[i]]; 94 sort(1,m); 95 for i:=1 to m do 96 ans:=ans+c[i]*(m-i+1); 97 writeln(ans:0:3); 98 end.