题目大意:给你一张无向图求合法的dfs序数量。dfs序不能在还可以dfs的时候退出。
n
≤
18
n\le18
n≤18。
题解:
设dp(S,x)表示,已经遍历了S(包括x),现在在x,然后接下来要从x出发遍历一个极大的集合的方案数(注意不是全集)。
首先如果不存在y使得
g
(
x
,
y
)
=
1
g(x,y)=1
g(x,y)=1且
{
y
}
∉
S
\{y\}\notin S
{y}∈/S,那么dp(S,x)=1并退出。
否则只要进入了y,就会遍历一个确定的点集并回到x,设这个点集是T,那么
d
p
(
S
∣
T
,
x
)
←
d
p
(
S
,
x
)
d
p
(
S
∣
{
y
}
,
y
)
dp(S|T,x)\leftarrow dp(S,x)dp(S|\{y\},y)
dp(S∣T,x)←dp(S,x)dp(S∣{y},y)。
T可以dfs求出。
#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<b;i++)
#define lint long long
#define mod 998244353
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
#define con(x,i) (((x)>>(i))&1)
#define lb(x) ((x)&-(x))
const int N=20,MXS=(1<<18)+10;int n,g[N][N],gs[N][MXS];lint dp[MXS][N];bool calc[MXS][N];
int dfs(int x,int s,int &v) { v|=(1<<x);rep(y,0,n) if(g[x][y]&&!con(s|v,y)) dfs(y,s,v);return 0; }
inline int go(int x,int s) { return ((!gs[x][s])?dfs(x,s,gs[x][s]):0),gs[x][s]; }
int main()
{
// freopen("data.in","r",stdin);
n=inn();int m=inn(),x,y,U=(1<<n)-1;lint ans=0;
rep(i,0,m) x=inn()-1,y=inn()-1,g[x][y]=g[y][x]=1;
for(int s=U;s>=0;s--) rep(x,0,n) if(con(s,x))
{
int v=1;
rep(y,0,n) if(g[x][y]&&!con(s,y))
dp[s][x]+=dp[s|go(y,s)][x]*dp[s|(1<<y)][y],v=0;
dp[s][x]+=v;
}
rep(x,0,n) ans+=dp[1<<x][x];return !printf("%lld\n",ans%mod);
}