您的位置:首页 > 其它

[状压DP][概率与期望][二分图] BZOJ 5006 && LOJ #2290. 「THUWC 2017」随机二分图

2017-12-26 19:37 369 查看

Solution

好神的做法。

如果只有type=0的话,直接状压DP就好了。

fS,T表示左边集合为S,右边匹配的集合为T的完备匹配的数量的期望。

而后面两种可以这么考虑把一组边拆掉。

type=1的话拆成两条50%可能出现的边和一组25%同时出现的边(若重点是不可能同时选的)。

这样的话同时出现的概率为50%×50%+25%=50%,两条边同时不出现的概率为(1−25%)−(50%×50%),一条边出现另一条边不出现的概率就为0。这样的连边方式就与原先等价了。

type=2的情况同上考虑,拆成两条50%可能出现的边和一组−25%同时出现的边。

显然暴力这么打复杂度过不去的。但理性分析一下给记忆化搜索的过程中的状态定个序,用map存一下就好了。

跑的好慢啊

#include <bits/stdc++.h>
using namespace std;

const int N = 16;
const int MOD = 1000000007;
const int INV2 = MOD + 1 >> 1;
const int INV4 = MOD + 1 >> 2;
typedef pair<int, int> Pairs;
typedef long long ll;

inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
template<typename T>
inline void read(T &x) {
static char c; x = 0; int sgn = 0;
for (c = get(); c < '0' || c > '9'; c = get()) if (c = '-') sgn = 1;
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
if (sgn) x = -x;
}

map<int, int> f[1 << N];
int n, m, Gcnt, t, x, y;
struct edge {
int S, p, c;
edge(int _S = 0, int _p = 0, int _c = 0): S(_S), p(_p), c(_c) {}
};
edge G[N * N << 2];

inline void Add(int &x, int a) {
x = (x + a) % MOD;
}
inline int F(int S) {
if (!S) return 1;
int T0 = S >> n, S0 = S ^ (T0 << n);
if (f[S0].count(T0)) return f[S0][T0];
int &g = f[S0][T0];
for (int i = 1; i <= Gcnt; i++) {
int T = G[i].S;
if ((T & S) == T && S < (T << 1))
Add(g, (ll)F(S ^ T) * G[i].p % MOD);
}
return g;
}

int main(void) {
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
read(n); read(m);
for (int i = 1; i <= m; i++) {
read(t); read(x); read(y);
int S1 = (1 << (x - 1)) | (1 << (y + n - 1));
G[++Gcnt] = edge(S1, INV2, 1);
if (t) {
read(x); read(y);
int S2 = (1 << (x - 1)) | (1 << (y + n - 1));
G[++Gcnt] = edge(S2, INV2, 1);
if (S1 & S2) continue;
if (t == 1) G[++Gcnt] = edge(S1 | S2, INV4, 2);
else G[++Gcnt] = edge(S1 | S2, MOD - INV4, 2);
}
}
cout << (1ll << n) * F((1 << (n * 2)) - 1) % MOD << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: