[ARC105] F - Lights Out on Connected Graph

题面

题目描述

无向图二分连通生成子图计数。

数据范围

  • \(1\leq n\leq 17\)

  • \(1\leq m \leq \frac{n(n-1)}{2}\)

题解

首先先对二分生成子图计数(不要求连通),记 \(f_{S}\) 表示 \(S\) 点集中可能的生成子图个数,\(E(S,T)\) 表示点集 \(S\) 与点集 \(T\) 之间的边数,通过枚举黑/白点集有转移式 \(\displaystyle f_S=\sum_{T\subseteq S} 2^{E(S/T,T)}f_T\),而 \(E(S/T,T)=E(S,S)-E(T,T)-E(S/T,S/T)\),可以预处理。注意此时对于每个二分图 \(G\) 都重复记了 \(2^{\operatorname{comp}(G)}\) 次。

然后现在要把不连通的斥掉。记 \(g_{S}\) 表示 \(S\) 点集中联通的生成子图个数,枚举 \(S\) 中最小值所在的连通块并减去,有转移式 \(\displaystyle g_S=f_S-\sum_{T\subset S\wedge \min(S) \in T} g_Tf_{S/T}\)

于是答案即为 \(\frac 12g_{\{1,2,...,n\}}\)\(\frac 12\) 是因为 \(2^{\operatorname{comp}(G)}=2^1=2\)

时间复杂度 \(O(3^n)\),瓶颈在于枚举子集。

#include<bits/stdc++.h>

using namespace std;

const int N=17+9;
const int M=17*17+9;
const int S=(1<<17)+9;
const int mod=998244353;
inline void AddAs(int &x,int y){if((x+=y)>=mod) x-=mod;}
inline void SubAs(int &x,int y){if((x-=y)<0) x+=mod;}
inline void MulAs(int &x,int y){x=1ll*x*y%mod;}
inline int Add(int x,int y){if((x+=y)>=mod) x-=mod;return x;}
inline int Sub(int x,int y){if((x-=y)<0) x+=mod;return x;}
inline int Mul(int x,int y){return 1ll*x*y%mod;}
inline int QPow(int x,int y){
    int res=1;
    while(y){
        if(y&1) MulAs(res,x);
        MulAs(x,x);
        y>>=1;
    }
    return res;
}
#define Inv(x) QPow(x,mod-2)

int u[M],v[M],n,m;
int cnt[S],f[S],g[S],pw[M];

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    #define endl '\n'

    cin>>n>>m;
    for(int i=1;i<=m;i++) cin>>u[i]>>v[i];
    pw[0]=1;for(int i=1;i<=m;i++) pw[i]=Add(pw[i-1],pw[i-1]);

    for(int sta=0;sta<(1<<n);sta++){
        for(int i=1;i<=m;i++) if((sta>>u[i]-1&1)&&(sta>>v[i]-1&1)) cnt[sta]++;
        for(int tta=sta;;tta=sta&tta-1){
            AddAs(f[sta],pw[cnt[sta]-cnt[tta]-cnt[sta^tta]]);
            if(!tta) break ;
        }
    }
    for(int sta=0;sta<(1<<n);sta++){
        g[sta]=f[sta];
        for(int tta=sta&sta-1;tta>(sta>>1);tta=sta&tta-1){
            SubAs(g[sta],Mul(g[tta],f[sta^tta]));
        }
    }

    cout<<Mul(g[(1<<n)-1],Inv(2))<<endl;

    return 0;
}
posted @ 2025-04-10 09:32  JoeyJiang  阅读(9)  评论(0)    收藏  举报