zoukankan      html  css  js  c++  java
  • 【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;
    }
    
    
  • 相关阅读:
    解决VsCode中Go插件依赖安装失败问题
    C# httpclient获取cookies实现模拟web登录
    C#中调用HttpWebRequest类中Get/Post请求无故失效的诡异问题
    VisualSVN 5.1.7破译License Key
    AutoResetEvent类的使用
    26种设计模式之单例模式
    WPF的一些感悟
    vim 常用指令
    myeclipse 的.jsp文件中的<option>无法使用
    flume部署问题解决
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/11146712.html
Copyright © 2011-2022 走看看