AtCoder Beginner Contest 213G - Connectivity 2(状压dp神仙题)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 213G - Connectivity 2(状压dp神仙题)相关的知识,希望对你有一定的参考价值。
题意
给定简单无向图 G = ( V , E ) G=(V,E) G=(V,E),点的编号从 1 1 1到 ∣ V ∣ = n |V|=n ∣V∣=n.对于 k = 2.. n k=2..n k=2..n,求 H = ( V , E ′ ⊆ E ) H=(V,E′⊆E) H=(V,E′⊆E) 的个数,使得 1 1 1 与 k k k 连通。
n ≤ 17 , m < = n ∗ ( n − 1 ) 2 n≤17,m<=\\frac{n*(n-1)}{2} n≤17,m<=2n∗(n−1)。
考虑最后图的状态,点 1 1 1和点 k k k处于同一个连通块,这个连通块到其他点没有边
定义全集 U = ( 1 < < n ) − 1 U=(1<<n)-1 U=(1<<n)−1
考虑枚举最后的这个点集 s s s包含点 1 , k 1,k 1,k,定义 c n t ( s ) cnt(s) cnt(s)表示子集 s s s中包含的边
f ( S ) f(S) f(S)表示利用这 c n t ( S ) cnt(S) cnt(S)条边把 S S S连通的方案数
答案为
a n s ( k ) = ∑ 1 ∈ S , k ∈ S f [ S ] ∗ 2 c n t ( U − S ) ans(k)=\\sum\\limits_{1\\in S,k\\in S}f[S]*2^{cnt(U-S)} ans(k)=1∈S,k∈S∑f[S]∗2cnt(U−S)
这样显然是正确的,因为 S S S内部连通,而 S S S点集和外面点之间的边都断掉,整下的 c n t ( U − S ) cnt(U-S) cnt(U−S)条边怎么放都可以
怎么计算 f ( S ) ? f(S)? f(S)?正着转移有重复,反着考虑
f ( S ) = 2 c n t ( S ) − ∑ T ∈ S & & S ! = T f ( T ) ∗ 2 S − T f(S)=2^{cnt(S)}-\\sum\\limits_{T\\in S\\&\\&S!=T}f(T)*2^{S-T} f(S)=2cnt(S)−T∈S&&S!=T∑f(T)∗2S−T
但是考虑到在不合法方案中 S S S中存在多个连通块,一个方案会在多个 T T T中被计算
所以我们任取其中一点,只计算这个点所在的连通块就是唯一的
这样的分割就是唯一的
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 998244353;
const int maxn = 1<<21;
int n,m,f[1<<17],g[1<<17],a[17*17],b[17*17],bit[17*17],ans[18];
signed main()
{
cin >> n >> m;
bit[0] = 1;
for(int i=1;i<=m;i++)
{
bit[i] = bit[i-1]*2%mod;
cin >> a[i] >> b[i];
a[i]--; b[i]--;
}
for(int i=0;i<(1<<n);i++)//计算每个点集内部的边数
{
for(int j=1;j<=m;j++)
if( ((i>>a[j])&1) && ((i>>b[j])&1) )
g[i]++;
}
for(int i=0;i<(1<<n);i++)
{
int x = 0;
for(int j=0;j<n;j++)
if( (i>>j)&1 ) { x = j; break; }
f[i] = bit[g[i]];
for(int j=(i-1)&i;j;j=(j-1)&i )
{
if( ((j>>x)&1)==0 ) continue;
f[i] = ( f[i]-f[j]*bit[g[i-j]]%mod )%mod;
}
}
for(int i=0;i<(1<<n);i++)
{
if( (i&1)==0 ) continue;
int temp = f[i]*bit[g[(1<<n)-1-i]]%mod;
for(int j=0;j<n;j++)
{
if( ((i>>j)&1)==0 ) continue;
ans[j] = ( ans[j]+temp )%mod;
}
}
for(int i=1;i<n;i++) cout << ( ans[i]%mod + mod )%mod << endl;
return 0;
}
以上是关于AtCoder Beginner Contest 213G - Connectivity 2(状压dp神仙题)的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Beginner Contest 115 题解