• NOIP模拟题 管道


     题目大意

    给定$n$个点的无向图,求它的$Dfs$序方案数
    $nleq 18$

    题解

    状压$Dp+$记忆化搜索。

    $F_{i,now}$表示到达$i$其中$now$集合代表的点集已经遍历过,还需要遍历其余点的方案数。

    考虑枚举$i$每一个不在点集内部的出边进行记忆化搜索转移。

    这样会有一个问题:无法解决回溯。

    考虑设$G_{i,now}$表示已选了点集$now$当前位置在$i$,能遍历到的所有最大状态,即当前情况下$i$的子树的集合与$now$的并集。

    $G_{i,now}$也可以用记忆化搜索处理。

    这样,对于每一个$F_{x,now}$,枚举每一个$ otin now$的$x$的后继$y$,

    $$F_{x,now}=sum F_{x,G_{y,now|y}} imes F_{y,now|y}$$

    复杂度$O(n^2 2^n)$

    #include<bits/stdc++.h>
    #define debug(x) cerr<<#x<<" = "<<x
    #define sp <<"  "
    #define el <<endl
    #define LL long long
    #define M 20
    #define mod 998244353
    using namespace std;
    int read(){
    	int nm=0,fh=1; char cw=getchar();
    	for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh;
    	for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
    	return nm*fh;
    }
    int n,m,fs[M],sz[M],c[M][M],F[19][1<<19],G[19][1<<19],ans;
    #define upd(x,y) x+=y,x=(x>=mod?x-mod:x)
    int Trans(int x,int now){
    	if(G[x][now]>=0) return G[x][now]; G[x][now]=now;
    	for(int k=1;k<=sz[x];k++){
    		int to=c[x][k]; if((now>>(to-1))&1) continue;
    		G[x][now]|=Trans(to,now|(1<<(to-1)));
    	}return G[x][now];
    }
    int Dp(int x,int now){
    	if(Trans(x,now)==now) return 1;
    	if(F[x][now]>=0) return F[x][now]; F[x][now]=0;
    	for(int k=1;k<=sz[x];k++){
    		int to=c[x][k];
    		if((now>>(to-1))&1) continue;
    		int t1=Dp(to,now|(1<<(to-1)));
    		int t2=Dp(x,now|Trans(to,now|(1<<(to-1))));
    		int res=(LL)t1*(LL)t2%mod; upd(F[x][now],res);
    	} return F[x][now];
    }
    int main(){
    	n=read(),m=read(),memset(G,-1,sizeof(G)),memset(F,-1,sizeof(F));
    	for(int i=1;i<=m;i++){int x=read(),y=read();c[x][++sz[x]]=y,c[y][++sz[y]]=x;}
    	for(int i=1;i<=n;i++) upd(ans,Dp(i,1<<(i-1))); printf("%d
    ",ans); return 0;
    }
  • 相关阅读:
    Linux系统管理上机作业2
    Linux系统管理上机作业1
    作业
    作业
    作业2
    作业
    作业
    第三章
    第二章
    第一章:计算机网络参考模型
  • 原文地址:https://www.cnblogs.com/OYJason/p/9908650.html
Copyright © 2020-2023  润新知