zoukankan      html  css  js  c++  java
  • bzoj3812 主旋律 容斥+状压 DP

    题目传送门

    https://lydsy.com/JudgeOnline/problem.php?id=3812

    题解

    考虑对于图的联通性的 DP 的一般套路:总方案 - 不连通的方案。

    那么我们只需要求出使得整个图不强联通的方案数即可。

    假设我们钦定了一个 (p) 点,然后通过枚举包含 (p) 点的强连通分量来转移。但是会遇到一些问题:不像无向图,无向图的不连通只需要保证没有边相连就可以了,但是有向图不行。

    有向图一定可以被缩点成一个 DAG,然后 (p) 点所在的连通块可能会连入边,也可能会连出边。这样就非常不好计算了。


    所以我们不妨考虑那些只会连入边的点——也就是出度为 (0) 的点。如果我们事先确定了一个强连通分量的出度为 (0),那么所有的可能存在的边就是剩下的点的所有出边了。

    但是因为出度为 (0) 的 SCC 不一定只有 (1) 个,所以可以考虑容斥。令 (f[S][0/1]) 表示 (S) 集合中的点构成了奇数/偶数个出度为 (1) 的 SCC 的总方案。(dp[S]) 表示使 (S) 集合中的点强联通的方案数。

    那么转移显然就是(为了防止计算重复,我们钦定一个点 (p) 为必须算的)

    [f[S][0] = sum_{ssubseteq S & p in s} f[S - s][1] cdot dp[s]\ f[S][1] = sum_{ssubseteq S & p in s} f[S - s][0] cdot dp[s] ]

    然后 (DP) 的时候就好办多了。建立一些辅助的数组:(w[s]) 表示 (s) 集合中的点向全集 (S) 中的点可以连多少边。

    [dp[S] = 2^{w_S} - sum_{s subseteq S} (f[s][1] - f[s][0]) 2^{w_s} ]

    (最后不要忘了把 (f[S][1]) 加上 (dp[S]) 因为 (dp[S]) 也是一种合法方案)


    下面是代码,时间复杂度为 (O(3^n))

    #include<bits/stdc++.h>
    
    #define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
    #define dbg(...) fprintf(stderr, __VA_ARGS__)
    #define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
    #define fi first
    #define se second
    #define pb push_back
    
    template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
    template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}
    
    typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
    
    template<typename I> inline void read(I &x) {
    	int f = 0, c;
    	while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
    	x = c & 15;
    	while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
    	f ? x = -x : 0;
    }
    
    #define lowbit(x) ((x) & -(x))
    
    const int N = 15 + 7;
    const int M = (1 << 15) + 7;
    const int P = 1e9 + 7;
    
    int n, m, S;
    int ind[N], oud[N], pw[N * N], ss[M];
    int pcnt[M], f[M][2], dp[M], w[M];
    
    inline int smod(int x) { return x >= P ? x - P : x; }
    inline void sadd(int &x, const int &y) { x += y; x >= P ? x -= P : x; }
    inline int fpow(int x, int y) {
    	int ans = 1;
    	for (; y; y >>= 1, x = (ll)x * x % P) if (y & 1) ans = (ll)ans * x % P;
    	return ans;
    }
    
    inline void ycl() {
    	S = (1 << n) - 1, pw[0] = 1;
    	for (int s = 1; s <= S; ++s) pcnt[s] = pcnt[s ^ lowbit(s)] + 1;
    	for (int i = 1; i <= m; ++i) pw[i] = smod(pw[i - 1] << 1);
    }
    
    inline void DP() {
    	for (int s = 1; s <= S; ++s) {
    		ss[0] = 0;
    		for (int sta = s; sta; sta = (sta - 1) & s) ss[++ss[0]] = sta;
    		for (int i = ss[0]; i; --i) w[ss[i]] = w[ss[i] ^ lowbit(ss[i])] + pcnt[oud[std::__lg(lowbit(ss[i])) + 1] & s];
    		dp[s] = pw[w[s]];
    		for (int sta = s & (s - 1); sta; sta = (sta - 1) & s)
    			if (sta & lowbit(s)) sadd(f[s][0], (ll)f[s ^ sta][1] * dp[sta] % P),
    			sadd(f[s][1], (ll)f[s ^ sta][0] * dp[sta] % P);
    		for (int sta = s; sta; sta = (sta - 1) & s) sadd(dp[s], (ll)(f[sta][0] - f[sta][1] + P) * pw[w[s ^ sta]] % P);
    		sadd(f[s][1], dp[s]);
    	}
    	printf("%d
    ", dp[S]);
    }
    
    inline void work() {
    	ycl();
    	DP();
    }
    
    inline void init() {
    	read(n), read(m);
    	int x, y;
    	for (int i = 1; i <= m; ++i) read(x), read(y), oud[x] |= 1 << (y - 1), ind[y] |= 1 << (x - 1);
    }
    
    int main() {
    #ifdef hzhkk
    	freopen("hkk.in", "r", stdin);
    #endif
    	init();
    	work();
    	fclose(stdin), fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    洛谷p1017 进制转换(2000noip提高组)
    Personal Training of RDC
    XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Eurasia
    XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Peterhof.
    Asia Hong Kong Regional Contest 2019
    XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Siberia
    XVIII Open Cup named after E.V. Pankratiev. Ukrainian Grand Prix.
    XVIII Open Cup named after E.V. Pankratiev. GP of SPb
    卜题仓库
    2014 ACM-ICPC Vietnam National First Round
  • 原文地址:https://www.cnblogs.com/hankeke/p/bzoj3812.html
Copyright © 2011-2022 走看看