之前我们曾经用dp解决过数学期望问题,这次我们用的是解方程的方法
首先在编号之前,肯定要求出每条边的期望经过次数
然后可以转化为求边端点的期望次数
这种做法我一开始接触是noip2013的初赛问题求解,是类似的思想
当出现循环无法用dp解决时,我们考虑列方程
设pi为点i的期望经过次数
则容易得到pi=sigma(pj/dj) dj表示出度,j是与i相邻的点
特殊的p1=1+sigma(pj/dj) pn=0(因为到n就停止了)
于是我们可以得到一个方程组,这样就可以用高斯消元求解
解出之后就能求出边的期望经过次数了,然后贪心分配编号即可
var w:array[..,..] of longint;
a:array[..,..] of double;
x,y:array[..] of longint;
c,p:array[..] of double;
d:array[..] of longint;
i,j,k,n,m:longint;
ans:double; procedure swap(var a,b:double);
var c:double;
begin
c:=a;
a:=b;
b:=c;
end; procedure calc;
var i,j,k,w:longint;
begin
for i:= to n do
begin
w:=i;
for k:=i+ to n do
if abs(a[k,i])>abs(a[w,i]) then w:=k;
if w<>i then
begin
for j:= to n+ do
swap(a[w,j],a[i,j]);
end;
for k:=i+ to n do
for j:=n+ downto i do
a[k,j]:=a[k,j]-a[i,j]*a[k,i]/a[i,i];
end;
p[n]:=;
for i:=n- downto do
begin
for j:=i+ to n do
a[i,n+]:=a[i,n+]-a[i,j]*p[j];
p[i]:=a[i,n+]/a[i,i];
end;
end; procedure sort(l,r: longint);
var i,j: longint;
x:double;
begin
i:=l;
j:=r;
x:=c[(l+r) shr ];
repeat
while c[i]<x do inc(i);
while x<c[j] do dec(j);
if not(i>j) then
begin
swap(c[i],c[j]);
inc(i);
j:=j-;
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end; begin
readln(n,m);
for i:= to m do
begin
readln(x[i],y[i]);
inc(d[x[i]]);
inc(d[y[i]]);
w[x[i],d[x[i]]]:=y[i];
w[y[i],d[y[i]]]:=x[i];
end;
a[,]:=-;
for i:= to d[] do
begin
k:=w[,i];
a[,k]:=/d[k];
end;
a[,n+]:=-;
for i:= to n- do
begin
for j:= to d[i] do
begin
k:=w[i,j];
a[i,k]:=/d[k];
end;
a[i,i]:=-;
end;
a[n,n]:=;
calc;
for i:= to m do
c[i]:=p[x[i]]/d[x[i]]+p[y[i]]/d[y[i]];
sort(,m);
for i:= to m do
ans:=ans+c[i]*(m-i+);
writeln(ans::);
end.