G - Rikka with Game Theory
题意 无向图SG值的可能数量 节点数 1 ≤ n ≤ 17 1 \leq n \leq 17 1≤n≤17
正赛的时候看最快7min出,想着算上找题和看题打代码的时间,这必是规律题(挨打
实际上是状压dp((
题解 所有为 0 的点一定是原图的一个极大独立集,所有为 1 的点一定是去掉为 0 的点后的一个极大独立集, 以此类推。直接状态压缩动态规划,时间复杂度 O ( 3 n ) O(3 ^ n) O(3n) 。
代码真的好妙
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 20;
int g[1 << maxn];
int w[1 << maxn];
ll dp[1 << maxn]; //注意数组范围!!!
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int n, m;
cin >> n >> m;
for(int i = 0, u, v; i < m; ++ i) {
cin >> u >> v;
-- u, -- v;
g[u] |= 1 << v;
g[v] |= 1 << u;
}
for(int i = 0; i < (1 << n); ++ i) {
for(int j = 0; j < n; ++ j) {
if(i & (1 << j)) w[i] |= g[j];
}
}
dp[0] = 1;
for(int i = 1; i < (1 << n); ++ i) {
for(int j = i; j; j = i & (j - 1)) { //遍历可能可以转移的状态
if( ((w[j] & j) == 0) //最大独立集
&& ((w[j] & (i ^ j)) == (i ^ j)) ) //都有边相连
dp[i] += dp[i ^ j];
}
}
cout << dp[(1 << n) - 1];
return 0;
}