zoukankan      html  css  js  c++  java
  • 51NOD 1833 环

       考虑一下简单环覆盖这个图的意义,其实就是找出原序列的所有排列,满足所有<i,a[i]>都是原图中的一条有向边。 因为一个置换就是由很多简单环构成的。

        于是我们可以设 f[i][S] 为考虑了前i个点的出边,且有入度的点集为S的方案数。 直接dp不难发现复杂度是 O(n^2 * 2^n),正好会T掉2333.

        但是进一步发现,因为每个点都要匹配另一个点,也就是说 S 集合中1的个数必须和i一样,所以预处理一下 bitcount 就可以把复杂度降到 O(n * 2^n)了。

    #include<bits/stdc++.h>
    #define ll long long
    const int ha=998244353;
    const int maxn=1100005;
    int f[maxn],n,m,ci[25],BT[maxn];
    bool G[25][25];
    inline void add(int &x,int y){ x+=y; if(x>+ha) x-=ha;}
    
    inline void dp(){
    	f[0]=1,BT[0]=0;
    	for(int i=1;i<ci[n];i++) BT[i]=BT[i^(i&-i)]+1;
    	for(int i=0;i<n;i++)
    	    for(int S=ci[n]-1;S>=0;S--) if(f[S]&&BT[S]==i)
    	        for(int j=0;j<n;j++) if(!(ci[j]&S)&&G[i][j]) add(f[S|ci[j]],f[S]);
    }
    
    int main(){
    	ci[0]=1;
    	for(int i=1;i<=20;i++) ci[i]=ci[i-1]<<1;
    	int uu,vv;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++) scanf("%d%d",&uu,&vv),G[uu-1][vv-1]=1;
    	dp();
    	printf("%d
    ",f[ci[n]-1]);
    	return 0;
    }
    

      

  • 相关阅读:
    20145220&20145209&20145309信息安全系统设计基础实验报告
    20145209 《信息安全系统设计基础》第8周学习总结
    R574
    gym102219
    102222F
    luogu 1337
    luogu 2503 & bzoj 2428
    18 BJ J
    poj 1981
    101992 I
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8880238.html
Copyright © 2011-2022 走看看