ATB213G 连通性·II 学习笔记
Luogu Link
题意简述
给定一张 \(n\) 点 \(m\) 边的简单无向图 \(G\)。考虑删去任意自然数条边构成一个新图 \(G'\)。对于每个点 \(2\le k\le n\),求有多少张新图满足点 \(k\) 与点 \(1\) 连通。
\(n\le 17\)。
做法解析
设 \(F_S\) 为只考虑点集 \(S\) 时连通子图的个数。这东西是好求的,正难则反,我们用所有方案数减去不连通子图的个数。对于求不连通子图的个数,我们钦定一个点 \(u\in S\),枚举 \(u\) 所在的连通块。则有柿子:\(F_S=2^{\text{ecnt}_S}-\sum_{u\in T \subset S} F_T-2^{\text{ecnt}_{S-T}}\)。
那么当我们求出了所有 \(F_S\) 的值之后,答案 \(\text{ans}_k\) 等于什么呢?我们既然要求 \(k\) 和 \(1\) 连通,那么我们沿用枚举所在连通块的点集的思想,枚举 \(1\) 和 \(k\) 所在的连通块点集,即:\(\text{ans}_k=\sum_{\{1,k\}\subset S\subset \text{ALF}}F_S\times 2^{\text{ecnt}_{\text{ALF}-S}}\)。
时间复杂度:\(n2^n+3^n\)。
代码实现
代码很简单!
#include <bits/stdc++.h>
using namespace std;
using namespace obasic;
using namespace omodint;
using mint=M998;
const int MaxN=17,MaxNr=3e2,MaxA=1<<17;
int N,M,alf,X,Y,Gr[MaxN],lg2[MaxA],ecn[MaxA];
void addudge(int u,int v){Gr[u]|=(1<<v),Gr[v]|=(1<<u);}
int lowbit(int x){return x&(-x);}
mint pw2[MaxNr],f[MaxA],ans[MaxN];
int main(){readi(N),readi(M),alf=(1<<N)-1;for(int i=2;i<=alf;i<<=1)lg2[i]=lg2[i/2]+1;pw2[0]=1;for(int i=1;i<=M;i++)pw2[i]=pw2[i-1]*2;for(int i=1;i<=M;i++)readi(X),readi(Y),addudge(X-1,Y-1);for(int s=1;s<=alf;s++){int l=lowbit(s),u=lg2[l],t=s-l;ecn[s]=ecn[t];for(int i=0;i<N;i++)if((t&(1<<i))&&(Gr[u]&(1<<i)))ecn[s]++;}f[0]=1;for(int s=1;s<=alf;s++){int l=lowbit(s),u=lg2[l];f[s]=pw2[ecn[s]];for(int t=(s-1)&s;t;t=(t-1)&s){if(t&l)f[s]-=f[t]*pw2[ecn[s-t]];}}for(int s=2;s<=alf;s++){for(int i=1,c;i<N;i++){c=(1<<i)|1;if((s&c)==c)ans[i]+=f[s]*pw2[ecn[alf-s]];}}for(int i=1;i<N;i++)writi(miti(ans[i])),puts("");return 0;
}
反思总结
这道无向图连通性状压计数启示我们,正难则反和枚举所在连通块思想要记好!