zoukankan      html  css  js  c++  java
  • 【清华集训2014】主旋律

    【清华集训2014】主旋律

    题目大意

    给定一张(n)个点(m)条边的无向图,保证该图整个图为一个强联通分量,保证无重边自环。
    现在需要求出:有多少种删边方案,使得删完边后,整个图依旧是一个强联通分量。
    数据范围:(nleq 15 , mleq n(n-1))

    题解

    容斥题是真的鸡贼......,这(TMD)是人能想出来的?
    希望下次自己再来看这篇题解的时候还能看懂吧......
    规定(E[U,V])表示出度在(U)中,入度在(V)中的所有边的集合,其中(U)(V)为点集。
    对于一个点集(S),我们随便连边,然后缩点。
    那么缩完点后,形成的一定是一个(DAG)
    我们枚举缩完点后,构成出度为(0)(scc)的点是哪些,设这个点集为(T)
    那么每一种(T)集合都可以与原来的某些连边方案对应起来。
    我们确定完(T)后,(S-T)中的点先让它随便连,然后(S-T)连向(T)中的边也可以随便连。
    我们可以暂时得到一个式子:

    [2^{E[S,S]} = sum_{Tsubset S,T eq null} g_T *2^{E[S-T,S-T]}*2^{E[S-T,T]} ]

    (f_S)表示连完(E[S,S])中的边后,(S)整张图为一个强联通分量的方案数,即题目所求。
    上式中(g_T)表示把(T)中的点连成若干强联通分量的方案数。
    显然,直接(g_T = sum_{s_1,s_2...,s_k} prod_{k} f_s)是不对的。
    因为由于(E[S-T,S-T])中的边也是随便连的,所以还有可能会形成其他的出度为(0)(scc)
    所以这里应该是存在一个容斥系数的,即:

    [g_T = sum_{s_1,s_2,...,s_k} coef_k*f_{s_1}f_{s_2}...f_{s_k} ]

    我们令这个式子为(g_T)的定义式。
    考虑一下这个容斥系数(coef)到底是什么。
    我们设(r_k)表示划分成(k)个出度为(0)(scc)的方案数应该要被算几遍,显然(r_k=1)
    然后我们来推容斥系数(coef)应该设为多少才能够使得计算出来的结果与(r_k)等效。
    对于被划分成(k)个出度为(0)(scc)的方案,
    它在划分为(k-1)个中被算了(inom{k}{k-1})次,在划分为(k-2)个中被算了(inom{k}{k-2})次......
    所以我们有:

    [r_k = sum_{j=1}^kinom{k}{j} coef_j ]

    显然是一个二项式反演,结合(r_k=1)与二项式定理我们可以得到:

    [coef_k = sum_{j=1}^k (-1)^{k-j}inom{k}{j} r_k = ((-1)+1)^k - inom{k}{0}(-1)^k =(-1)^{k+1} ]

    所以我们得到了容斥系数(coef_k = (-1)^{k+1}),带入之前(g_T)的定义式中:

    [g_T = sum_{s_1,s_2,...,s_k} (-1)^{k+1} coef_k*f_{s_1}f_{s_2}...f_{s_k} ]

    根据容斥系数可以看出,(g_{null} = -1)
    现在我们终于弄清楚(g_T)究竟应该是什么了!
    到此为止,所有的准备工作已经就绪,下面开始求答案。
    回到这个式子:

    [2^{E[S,S]} = sum_{Tsubset S , T eq null} g_T *2^{E[S-T,S-T]}*2^{E[S-T,T]} ]

    注意到这个式子中是没有(f)数组的,所以:

    [g_S = 2^{E[S,S]} - sum_{Tsubsetneqq S , T eq null} g_T *2^{S-T,S-T} * 2^{E[S-T,T]} ]

    所以顺次把(g)数组全部推出来即可。
    然后我们来研究一下(g)的定义式:

    [g_T = sum_{s_1,s_2,...,s_k} (-1)^{k+1} coef_k*f_{s_1}f_{s_2}...f_{s_k} ]

    注意到,每加入一个(scc),容斥系数会乘上一个(-1)
    由于是无序关系,所以我们可以枚举最小编号所在的强联通分量(s_1),然后就可以得到:

    [g_T = (-1) * sum_{s_1 subset T , s_1 eq null} f_{s_1} g_{T-s_1} ]

    类似之前求(g)的技巧,移项可以得到:

    [f_T = g_T + sum_{s_1 subsetneqq T, s_1 eq null} f_{s_1} g_{T-s_1} ]

    所以说只要解决了(g),就可以顺次推出(f),而(g)我们已经会求了,所以就做完了。
    累死我了.......
    不玩了不玩了,再以不玩这种毒瘤题了......

    实现代码

    #include<bits/stdc++.h>
    #define IL inline
    #define mod 1000000007
    using namespace std ;
    
    int lk[20][20],Inside[(1<<17)],Edge[(1<<17)][20],n,m,pw[233333],pos[(1<<17)] ;
    int f[(1<<17)] , g[(1<<17)] , num[(1<<17)] , mx ; 
    
    IL void Pre() {
    	for(int i = 1,u,v; i <= m; i ++) cin >> u >> v , lk[u][v] ++ ;
    	mx = (1 << n) ; 
    	for(int S = 0; S < mx; S ++)
    		for(int i = 1; i <= n; i ++)
    			for(int j = 1; j <= n; j ++)
    				if((S&(1<<(i-1))) && (S&(1<<(j-1)))) Inside[S] += lk[i][j] ;
    	for(int S = 0; S < mx; S ++)
    		for(int v = 1; v <= n; v ++) if(S & (1 << (v - 1))) continue ;
    			else for(int u = 1; u <= n; u ++)
    					 if(S & (1 << (u - 1))) Edge[S][v] += lk[u][v] ;
    	for(int S = 0; S < mx; S ++) {
    		for(int v = 1; v <= n; v ++) if(S & (1 << (v - 1))) pos[S] = v ;
    	}
    	pw[0] = 1 ;
    	for(int i = 1; i <= m; i ++) pw[i] = (pw[i - 1] << 1) % mod ; return ; 
    }
    
    IL void add(int &x , int y) {x += y ; if(x >= mod) x -= mod ; }
    
    int main() {
    	freopen("scon.in","r",stdin) ;
    	freopen("scon.out","w",stdout) ;
    	cin >> n >> m ;
    	Pre() ; 
    	g[0] = mod - 1 ;
    	for(int S = 1; S < mx; S ++) {
    		g[S] = pw[Inside[S]] ;
    		for(int T = S,tmp; T ; T = (T - 1) & S) {
    			num[T] = 0 ; tmp = T ; while(tmp) add(num[T] , Edge[S ^ T][pos[tmp]]) , tmp -= (1 << (pos[tmp] - 1)) ;
    		}
    		for(int T = S; T ; T = (T - 1) & S) 
    			if(S ^ T) add(g[S] , mod - 1ll * g[T] * pw[Inside[S ^ T]] % mod * pw[num[T]] % mod) ;
    	}
    	for(int S = 1; S < mx; S ++) {
    		for(int s1 = S; s1 ; s1 = (s1 - 1) & S) {
    			if(s1 & (1 << (pos[S] - 1))) add(f[S] , 1ll * f[s1] * g[S ^ s1] % mod) ; 
    		}
    		add(f[S] , g[S]) ; 
    	}
    	cout << f[mx - 1] << endl ; return 0 ; 
    }
    

  • 相关阅读:
    [Automation] 自动化测试工具和测试框架大集合
    C#借助API实现黑盒自动化测试工具的编写
    C#实现RSA加密解密
    Uipath开发过程中最常见的5类错误
    tqdm介绍及常用方法
    Top-1准确率和Top-5准确率
    focal loss焦点损失
    【深度学习】卷积神经网络中Dropout、BatchNorm的位置选择
    数据增强——mixup
    数据增强之mixup算法详解
  • 原文地址:https://www.cnblogs.com/GuessYCB/p/10055724.html
Copyright © 2011-2022 走看看