[jzoj]5957. 【NOIP2018模拟11.7A组】scarborough fair(期望计数)

探讨了在给定无向图中,每条边有特定联通概率的情况下,如何计算图的期望联通块个数。通过逆向思考,计算每个联通块不连通的概率,并利用递归公式进行枚举计算,最终得出整个图的期望联通块数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem

  • 给定一个(n,m)(n,m)(n,m)的无向图,其中第iii条边联通的概率是WiW_iWi,求这个无向图的期望联通块个数。

  • n≤17,m≤n∗(n−1)2n\le 17, m\le \frac{n*(n-1)}{2}n17,m2n(n1).

Solution

  • 求期望联通块个数,那肯定得单独考虑每个联通块对答案的贡献,这种套路太常见了.

  • 我们只需计算出一个联通块它联通的概率,再乘上一个联通块(等价于一个点集)不再联通其他点的概率,累加起来就是答案了.

  • 计算前者,我们发现正着做并不好做,所以我们正难则反,考虑这个联通块不连通的概率即可,要计算这个概率,很显然是要枚举最小编号所在的块,这个套路也太常见了,然后计算即可.

  • 这里的时间复杂度是O(3n)O(3^n)O(3n)的,因为是枚举子集中的子集.

  • 我们把式子列一列,令fif_ifi表示iii这个点集不连通的概率.

  • 那么有fi=∑j∈i且j包含i中最后一个1fj∗Pj,i−jf_i=\sum_{j\in i 且 j包含i中最后一个1}f_j * P_{j,i-j}fi=jiji1fjPj,ijP[i][j]P[i][j]P[i][j]表示的含义是iiijjj这个点集没有边相连的概率。

  • 显然Pj,i−j=bet(i)bet(j)⋅bet(i−j)P_{j,i-j}=\frac{bet(i)}{bet(j)·bet(i-j)}Pj,ij=bet(j)bet(ij)bet(i)bet(i)bet(i)bet(i)则表示iii这个点集内的点都没有边相连的概率。

  • 最后calc计算答案也是类似的过程.

Code

#include <cstdio>
#include <cstring>

#define ll long long
#define F(i, a, b) for (ll i = a; i <= b; i ++)

const ll N = 18, M = N * (N - 1) / 2, Mo = 998244353;

ll n, m, u[M], v[M], w[M], vis[N];
ll fa[N], Ans, cnt;

ll get(ll x) {
	return !fa[x] ? x : get(fa[x]);
}

void Dfs(ll k, ll G) {
	if (k > m) {
		memset(vis, 0, sizeof vis), cnt = 0;
		F(i, 1, n)
			if (!vis[get(i)])
				vis[get(i)] = 1, cnt ++;
		Ans = (Ans + cnt * G) % Mo;
		return;
	}
	
	ll t = get(u[k]), tmp = fa[t];
	if (t ^ get(v[k]))
		fa[t] = get(v[k]);
	Dfs(k + 1, (G * (Mo + 1 - w[k])) % Mo);
	fa[t] = tmp;

	Dfs(k + 1, (G * w[k]) % Mo);
}

int main() {
	freopen("fair.in", "r", stdin);
	freopen("fair.out", "w", stdout);

	scanf("%d%d", &n, &m);
	F(i, 1, m)
		scanf("%d%d%d", &u[i], &v[i], &w[i]);

	Dfs(1, 1);

	printf("%d\n", Ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值