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

题意:给定一张点数不超过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爆炸退役
 1 var dp:array[0..3000,0..200]of extended;
 2     a:array[1..20,1..20]of longint;
 3     cnt:array[0..3000]of longint;
 4     c:array[0..3000,0..3000]of extended;
 5     n,m,i,sta,k,t,j,x,y:longint;
 6     ans:extended;
 7 
 8 function lowbit(x:longint):longint;
 9 begin
10  exit(x and (-x));
11 end;
12 
13 begin
14  assign(input,'bzoj3925.in'); reset(input);
15  assign(output,'bzoj3925.out'); rewrite(output);
16  read(n,m);
17  for i:=1 to m do
18  begin
19   read(x,y);
20   a[x,y]:=1; a[y,x]:=1;
21  end;
22  c[0,0]:=1;
23  for i:=1 to m do
24  begin
25   c[i,0]:=1;
26   for j:=1 to i do c[i,j]:=c[i-1,j-1]+c[i-1,j];
27  end;
28  for sta:=0 to (1<<n)-1 do
29  begin
30   for i:=1 to n do
31    for j:=1 to n do
32     if (a[i,j]=1)and
33        (sta and (1<<(i-1))>0)and(sta and (1<<(j-1))>0) then inc(cnt[sta]);
34   cnt[sta]:=cnt[sta]>>1;
35  end;
36  for sta:=0 to (1<<n)-1 do
37  begin
38   t:=lowbit(sta);
39   k:=sta and (sta-1);
40   while k>0 do
41   begin
42    if k and t=0 then begin k:=sta and (k-1); continue; end;
43    for i:=0 to cnt[sta] do
44     for j:=0 to i do
45      dp[sta,i]:=dp[sta,i]+(c[cnt[k],j]-dp[k,j])*c[cnt[sta xor k],i-j];
46    k:=sta and (k-1);
47   end;
48  end;
49  for i:=0 to cnt[(1<<n)-1] do ans:=ans+dp[(1<<n)-1,i]/c[cnt[(1<<n)-1],i];
50  ans:=ans/(m+1);
51  writeln(ans:0:6);
52 
53  close(input);
54  close(output);
55 end.
原文地址:https://www.cnblogs.com/myx12345/p/6757073.html