LINK:洛谷
题目大意:
现在有一个$n$个点,$m$条边的无向图,每条边的边权是一个$[0,1]$的随机实数,求最小生成树的最大权值$X$的期望。
$n\leq 10,m\leq \frac{n*(n-1)}{2}$
这道题有非常多的做法,其中我写一个数学味道最浓的做法。
设$p(t)=P'(t),P(t)=Pr(X\geq t)$,显然$p(t)$表示$X=t$的概率。
则答案就是$$\int_{0}^1p(x)xdx=\int_{0}^1p(x)\int_{0}^xdtdx$$
$$=\int_{0}^1\int_{t}^{1}p(x)dxdt$$
$$=\int_{0}^1P(t)dt$$
现在我们考虑如何求它。
我们考虑对子集dp。
但是在不连通的情况下,有很多个集合,我们要选取哪一个呢?
其实都是可以的,因为联通之后只有一个集合,所以我们钦定一个点1,设$S$为在$t$时刻时与1联通的所有点。
设$P_S(t)$为点集$S$对应的$P(t)$。
我们需要$X\geq t$,所以这个图在$t$时刻不连通,设$t$时刻与$1$联通的有$S0$这些点,则$S0$联通且$S0$与$S-S0$之间的所有边的权值$>t$
我们用$T(S1,S2)$表示$S1$和$S2$之间的边的数量。
$$P_S(t)=\sum_{1\in S_0\subset S}(1-t)^{T(S_0,S-S_0)}(1-P_{S_0}(t))$$
所以
$$\int_{0}^1P_S(t)(1-t)^kdt=\sum_{1\in S_0\subset S}\int_{0}^1(1-t)^{T(S_0,S-S_0)+k}(1-P_{S_0}(t))dt$$
$$=\sum_{1\in S_0\subset S}(\int_0^1(1-t)^{T(S_0,S-S_0)+k}dt-\int_0^1(1-t)^{T(S_0,S-S_0)+k}P_{S_0}(t)dt)$$
$$=\sum_{1\in S_0\subset S}(\frac{1}{1+k+T(S_0,S-S_0)}-\int_0^1(1-t)^{T(S_0,S-S_0)+k}P_{S_0}(t)dt)$$
然后我们就可以开始dp了
设$dp[S][k]$表示$\int_{0}^1P_S(t)(1-t)^kdt$
然后代码出奇的短。
复杂度$O(3^n*m)$,但是这是一个较松的上界。
1 #include<cstdio> 2 #define Rint register int 3 using namespace std; 4 int n, m, link[1 << 10], siz[1 << 10]; 5 double f[1 << 10][46]; 6 int main(){ 7 scanf("%d%d", &n, &m); 8 for(Rint i = 1;i <= m;i ++){ 9 int x, y; 10 scanf("%d%d", &x, &y); -- x; -- y; 11 link[x] |= (1 << y); 12 link[y] |= (1 << x); 13 } 14 for(Rint i = 1;i < (1 << n);i ++) siz[i] = siz[i & (i - 1)] + 1; 15 for(Rint S = 3;S < (1 << n);S += 2){ 16 for(Rint S0 = (S - 1) & S;S0;S0 = (S0 - 1) & S) if(S0 & 1){ 17 int T = 0; 18 for(Rint i = 0;i < n;i ++) if((S >> i) & (~S0 >> i) & 1) 19 T += siz[link[i] & S0]; 20 for(Rint i = 0;i + T <= m;i ++) 21 f[S][i] += 1.0 / (1 + i + T) - f[S0][i + T]; 22 } 23 } 24 printf("%.6lf\n", f[(1 << n) - 1][0]); 25 }