[ABC213G] Connectivity 2

题目

幸亏状压DP的数据范围明显,不然自己估计想不出来

解法

先考虑答案如何计算,比如计算点 k k k的答案,可以枚举包含 1 , k 1,k 1,k 的联通子图,然后每一个联通子图的方案数乘上无关的边就行。
形式化地, 设 G G G 为全图的点集 , S S S G G G 的一个子图, f S f_{S} fS 表示 S S S 的联通子图的方案数, g S g_{S} gS 为S的子图数,那我们有:
a n s k = ∑ { 1 , k } ∈ S f S ∗ g ∁ G S ans_k=\sum_{\{1,k\}\in S} f_{S} *g_{\complement_{G}S } ansk={1,k}SfSgGS
考虑计算 f , g f,g f,g 由于点很少,我们用二进制数表示状态,用 状压 D P DP DP 解决
g g g 用点的个数就可以求, 2 c n t S 2^{cnt_S} 2cntS , c n t S cnt_S cntS S S S 的点数
f S = g S − ∑ 1 ∈ T ⊂ S f T ∗ g ∁ S T f_{S}=g_{S}-\sum_{1\in T\subset S} f_{T} *g_{\complement_{S}T} fS=gS1TSfTgST

Code

#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const int N=(1<<17)+7,mod=998244353;
int n,m;
ll g[N],f[N],t[205];
vector G[N];
void Get_g() {
    g[0]=1;
    for(int mask=1;mask<(1<>i&1) {
            for(int j:G[i+1]) 
                if(mask>>(j-1)&1) tmp++;
        } g[mask]=t[(tmp>>1)];
    }
}
void Get_f() {
    for(int mask=1;mask<(1<>(i-1)&1) tmp=(tmp+f[mask]*g[((1<

TXL

你可能感兴趣的:(计数DP,动态规划,图论,算法)