【BZOJ3925】地震后的幻想乡(期望概率DP,状压DP)

时间:2024-11-18 09:04:55

题意:给定一张点数不超过10的无向连通图,每条边有一个[0,1]之间的随机权值,求最小生成树上最大边的期望值

提示:对于n个[0,1]之间的随机变量x1,x2,...,xn,第k小的那个的期望值是k/(n+1)。

思路:From http://www.cnblogs.com/ihopenot/p/6606665.html

题目后面的小提示很有用,问题实际上就转化为了求用k条边使原图恰好联通的概率。
但是恰好联通是个很蛋疼的条件,所以我们稍微把问题再变一变,我们去求用k条边原图仍不联通的概率
设f[S][k]为用了k条边原图的子集S仍不联通的方案数,总方案数显然为C[S中的边数][k]。
那么这样的话,每种边数对答案的贡献就是(f[S][k]/C[S][k])*(1/(m+1))
因为每条边无法联通图的话必然会让下一条边的期望增加1/(m+1)
那么关键就是求解 f
对于不连通图的计数可以固定某个点,枚举连通块,去不重不漏地计数
所以我们的 f 用这种方法去转移
静待Round 2爆炸退役
 var dp:array[..,..]of extended;
a:array[..,..]of longint;
cnt:array[..]of longint;
c:array[..,..]of extended;
n,m,i,sta,k,t,j,x,y:longint;
ans:extended; function lowbit(x:longint):longint;
begin
exit(x and (-x));
end; begin
assign(input,'bzoj3925.in'); reset(input);
assign(output,'bzoj3925.out'); rewrite(output);
read(n,m);
for i:= to m do
begin
read(x,y);
a[x,y]:=; a[y,x]:=;
end;
c[,]:=;
for i:= to m do
begin
c[i,]:=;
for j:= to i do c[i,j]:=c[i-,j-]+c[i-,j];
end;
for sta:= to (<<n)- do
begin
for i:= to n do
for j:= to n do
if (a[i,j]=)and
(sta and (<<(i-))>)and(sta and (<<(j-))>) then inc(cnt[sta]);
cnt[sta]:=cnt[sta]>>;
end;
for sta:= to (<<n)- do
begin
t:=lowbit(sta);
k:=sta and (sta-);
while k> do
begin
if k and t= then begin k:=sta and (k-); continue; end;
for i:= to cnt[sta] do
for j:= to i do
dp[sta,i]:=dp[sta,i]+(c[cnt[k],j]-dp[k,j])*c[cnt[sta xor k],i-j];
k:=sta and (k-);
end;
end;
for i:= to cnt[(<<n)-] do ans:=ans+dp[(<<n)-,i]/c[cnt[(<<n)-],i];
ans:=ans/(m+);
writeln(ans::); close(input);
close(output);
end.