• 【JZOJ5739】【20190706】毒奶


    题目

    (n)个现实城市,另有(n)个幻想城市

    原图中在现实城市存在(m)条边,在幻想城市存在(m-1-n)条边

    一个排列是合法的当且进当显示城市 (i) 向幻想城市 (p_i) 连边后,图是连通的

    求合法的排列数目

    (n le 20 , 时限10s)

    题解

    • 如果初始连通块个数(gt n+1)个无解;
    • 考虑这(n+1)个连通块,设(S)表示已经分配好的连通块集合的合法排列个数
    • 转移时用总的减去不合法的,不合法考虑枚举编号最小的城市所在联通块
    • 时间复杂度:(O(3^{20}))
    • 由于一个状态如果不满足现实和幻想的连通块点数和相等就是无用的,可以去掉很多无用状态

    Code

    #include<bits/stdc++.h>
    #define mod 998244353
    using namespace std;
    const int N=21;
    int n,m,n1,n2,tot,f[N],sz[N],sz1[1<<N],sz2[1<<N],all1,all2,all,fac[N],F[1<<N],G[1<<N];
    int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
    void dec(int&x,int y){x-=y;if(x<0)x+=mod;}
    void uni(int u,int v){
    	int fu=find(u),fv=find(v);
    	if(fu==fv)return;
    	f[fu]=fv;sz[fv]+=sz[fu];
    }
    int main(){
    	freopen("milk.in","r",stdin);
    	freopen("milk.out","w",stdout);
    	
    	scanf("%d%d",&n,&m);
    	for(int i=fac[0]=1;i<=n;++i)fac[i]=1ll*fac[i-1]*i%mod;
    	
    	for(int i=1;i<=n;++i)f[i]=i,sz[i]=1;
    	for(int i=1,u,v;i<=m;++i){
    		scanf("%d%d",&u,&v);
    		uni(u,v);
    	}
    	for(int i=1;i<=n;++i)if(find(i)==i){
    		sz1[1<<tot++]=sz[i];
    	}
    	n1=tot;tot=0;all1=(1<<n1)-1;
    	for(int i=0;i<n1;++i)
    	for(int j=0;j<=all1;++j)
    		if(j>>i&1)sz1[j]+=sz1[j^(1<<i)];
    	
    	m=n-1-m;
    	for(int i=1;i<=n;++i)f[i]=i,sz[i]=1;
    	for(int i=1,u,v;i<=m;++i){
    		scanf("%d%d",&u,&v);
    		uni(u,v);
    	}
    	for(int i=1;i<=n;++i)if(find(i)==i){
    		sz2[1<<tot++]=sz[i];
    	}
    	n2=tot;tot=0;all2=(1<<n2)-1;
    	for(int i=0;i<n2;++i)
    	for(int j=0;j<=all2;++j)
    		if(j>>i&1)sz2[j]+=sz2[j^(1<<i)];
    	
    	all=(1<<(n1+n2))-1;
    	if(n1+n2!=n+1){puts("0");return 0;}
    	F[0]=G[0]=1;
    	for(int S=1;S<=all;++S){
    		int v1=sz1[S&all1],v2=sz2[S>>n1];
    		if(v1!=v2)continue;
    		G[S]=fac[v1];
    	}
    	for(int S=1;S<=all;++S)if(G[S]){
    		F[S]=G[S];
    		int x=S&-S,R=S^x;
    		if(x>all1)continue;
    		for(int T=R;T;T=(T-1)&R)if(G[T]){
    			dec(F[S],1ll*G[T]*F[S^T]%mod);
    		}
    	}
    	cout<<F[all]<<endl;
    	return 0;
    }
    
    
  • 相关阅读:
    12款响应式的 jQuery 旋转木马(传送带)插件
    CSS预处理器实践之Sass、Less大比拼[转]
    jQuery学习笔记
    7件你不知道但可以用CSS做的事
    纯js页面跳转整理
    JavaScript中this的工作原理以及注意事项
    CSS Hack大全-可区分出IE6-IE10、FireFox、Chrome、Opera
    为现代JavaScript开发做好准备
    15 个最佳的 jQuery 表格插件
    全栈式JavaScript
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/11146712.html
Copyright © 2020-2023  润新知