Loading

【题解】[CERC2016]二分毯 Bipartite Blanket

前置知识:霍尔定理

对于二分图,两部分别为 \(X,Y\),令 \(|X| \le |Y|\),则存在大小为 \(X\) 的匹配的充要条件是对于任意 \(S\subseteq X\),都有 \(|F(S)| \ge |S|\),其中 \(F(S) = \{y\ |\ x\to y \in E,x\in S,y\in Y\}\)

说人话就是对于 \(X\) 的所有子集,相邻的点数都不小于子集。

必要性显然,充分性不显然,反证一下。

假设满足条件但是匹配 \(<|X|\),那么不妨令没有匹配的点为 \(x\)\(x\) 的所有邻居都被匹配了,此时从 \(x\) 出发一定存在一条增广路(匈牙利算法),如果不存在,则假设这条非增广路经过 \(X\) 的点集为 \(X'\)\(|F(X')|\) 一定 \(<|X'|\),手动画图即可理解。

那么对于本题关键结论是

\(V\)\(X\) 中的点集为 \(S\)\(Y\) 中的点集为 \(T\)。如果存在匹配覆盖 \(S\),并存在匹配覆盖 \(T\),则一定存在匹配覆盖 \(V\)

这结论挺好猜的,\(N\le 20\) 显然就是折半然后双指针嘛。证明也不难。

\(S\)\(T\) 中的邻居为 \(W\)\(S\) 和它的邻居匹配,然后 \(T/W\) 再进行匹配即可。

所以直接状压 DP,\(f_S\) 表示集合 \(S\) 的邻居集合,\(h_{S}\) 表示集合 \(S\) 是否合法,直接转移 \(\mathcal{O}(n^22^n + m^22 ^m)\)

#define N 20
#define M ((1 << N) + 5)
int n, m, u[M], v[M], f[M], bt[M], g[M], p[M], q[M], l, r, h[M], a[M], b[M]; char s[N + 1];
int main() {
	read(n, m);
	rep(i, 0, n - 1){
		scanf("%s", s);
		rep(j, 0, m - 1)if(s[j] == '1')u[1 << i] |= 1 << j, v[1 << j] |= 1 << i;
	}
	rep(i, 0, n - 1)read(p[1 << i]);
	rep(i, 0, m - 1)read(q[1 << i]);
	int w = (1 << max(n, m)) - 1;
	rp(i, w)bt[i] = bt[i >> 1] + (i & 1);
	w = (1 << n) - 1;
	h[0] = 1;
	rp(i, w){
		int j = i & -i;
		p[i] = p[j] + p[i ^ j];
		f[i] = u[j] | f[i ^ j];
		h[i] = 1;
		for(int k = i; k; k -= k & -k)h[i] &= h[i ^ (k & -k)];
		h[i] &= bt[f[i]] >= bt[i];
		if(h[i])a[++l] = p[i];
	}a[++l] = 0;
	w = (1 << m) - 1;
	rp(i, w){
		int j = i & -i;
		q[i] = q[j] + q[i ^ j];
		g[i] = v[j] | g[i ^ j];
		h[i] = 1;
		for(int k = i; k; k -= k & -k)h[i] &= h[i ^ (k & -k)];
		h[i] &= bt[g[i]] >= bt[i];
		if(h[i])b[++r] = q[i];
	}b[++r] = 0;
	sort(a + 1, a + l + 1),
	sort(b + 1, b + r + 1);
	read(w);
	int j = r; LL ans = 0;
	rp(i, l){
		while(j && b[j] + a[i] >= w)j--;
		ans += r - j;
	}printf("%lld\n", ans);
	return 0;
}
posted @ 2022-04-09 21:38  7KByte  阅读(46)  评论(0编辑  收藏  举报