待补 重要思考:求给无向图定向使得其变为DAG的方案数

今天比赛考到了,不会,丢了 100 分。

rk2,380 -> rk15,280

别问为什么 T4 没过,因为不会 T2。

方法一 O(3n)

fS 为子集 S 内定向得到 DAG 的方案。

fS=TS,T 为独立集(1)|T|1fST

考虑 DAG 的分解构造过程,可以将其分为出/入度等于 0 的最大点集,删除/剥离一层继续这样,考虑逆向构造 DAG,但是发现存在重复计数,可以采用容斥,对于非空点集 T,容斥系数为 (1)|T|1

关于容斥系数:有机会总结一下。关于本题,设 T 的计算容斥系数为 g(T),而真实容斥系数为 1,根据计算方式,大的会被每个小的计算一次(有些时候是有关组合数的系数,但这里根据定义和公式是 1 次),于是有 S,TSg(T)=1

可以构造 g(T)=(1)|T|1

枚举子集复杂度 O(3n)。考虑是不是可以 O(3n) 求得容斥系数?

code
const int N = 20;
const int mod = 1e9 + 7;

int n, m;
int to[N];
int f[1 << N], g[1 << N];

inline void qadd(int &a, int b) {
	a += b;
	if (a >= mod) a -= mod;
}

void calc() {
	read(n, m);
	rep (i, 1, m) {
		int a, b; read(a, b);
		--a; --b;
		to[a] |= 1 << b;
		to[b] |= 1 << a;
	}
	g[0] = 1;
	rep (s, 1, (1 << n) - 1) {
		rep (j, 0, n - 1) {
			if (s >> j & 1) {
				g[s] = g[s ^ (1 << j)] & ((s & to[j]) == 0);
				break;
			}
		}
	}

	f[0] = 1;
	rep (s, 1, (1 << n) - 1) {
		for (int t = s; t; t = (t - 1) & s) {
			if (g[t] && f[s ^ t]) {
				if (__builtin_popcount(t) & 1) qadd(f[s], f[s ^ t]);
				else qadd(f[s], mod - f[s ^ t]);
			}
		}
	}
	write(f[(1 << n) - 1]);
}

方法二 O(n22n)

貌似子集卷积,记得补

1 LUOGU

2 NFLS

posted @   SkyMaths  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示