• Solution -「SHOI2016」「洛谷 P4336」黑暗前的幻想乡


    (mathcal{Description})

      link.
      有一个 (n) 个结点的无向图,给定 (n-1) 组边集,求从每组边集选出恰一条边最终构成树的方案树。对 (10^9+7) 取模。
      (2le nle17),边集大小 (0le m_ilefrac{n(n-1)}2)

    (mathcal{Solution})

      (n) 很小,考虑容斥。枚举这 (n-1) 个边集的子集,将子集内的边集的边加入图,用矩阵树定理求出生成树个数,容斥一下就好啦。复杂度 (mathcal O(2^nn^3))

    (mathcal{Code})

    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    
    const int MAXN = 17, MOD = 1e9 + 7;
    int n, m, d[MAXN + 5][MAXN + 5];
    std::vector<std::pair<int, int> > able[MAXN + 5]; 
    
    inline int qkpow ( int a, int b, const int p = MOD ) {
    	int ret = 1;
    	for ( ; b; a = 1ll * a * a % p, b >>= 1 ) ret = 1ll * ret * ( b & 1 ? a : 1 ) % p;
    	return ret;
    }
    
    inline int det ( int d[MAXN + 5][MAXN + 5] ) {
    	int ret = 1, swp = 1;
    	for ( int i = 1; i < n; ++ i ) {
    		for ( int j = i; j < n; ++ j ) {
    			if ( d[j][i] ) {
    				if ( i ^ j ) std::swap ( d[i], d[j] ), swp *= -1;
    				break;
    			}
    		}
    		if ( ! d[i][i] ) return 0;
    		ret = 1ll * ret * d[i][i] % MOD;
    		int inv = qkpow ( d[i][i], MOD - 2 );
    		for ( int j = i + 1; j < n; ++ j ) {
    			int c = 1ll * inv * d[j][i] % MOD;
    			for ( int k = i; k < n; ++ k ) d[j][k] = ( d[j][k] - 1ll * c * d[i][k] % MOD + MOD ) % MOD;
    		}
    	}
    	return ( ret * swp + MOD ) % MOD;
    }
    
    int main () {
    	scanf ( "%d", &n );
    	for ( int i = 1, m; i < n; ++ i ) {
    		scanf ( "%d", &m );
    		for ( int u, v; m --; ) {
    			scanf ( "%d %d", &u, &v );
    			able[i].push_back ( { u, v } );
    		}
    	}
    	int ans = 0;
    	for ( int s = 1; s < 1 << n >> 1; ++ s ) {
    		int bit = 0; memset ( d, 0, sizeof d );
    		for ( int i = 1; i < n; ++ i ) {
    			if ( ( s >> i - 1 ) & 1 ) {
    				++ bit;
    				for ( int j = 0; j ^ able[i].size (); ++ j ) {
    					int u = able[i][j].first, v = able[i][j].second;
    					++ d[u][u], ++ d[v][v], -- d[u][v], -- d[v][u];
    					if ( d[u][v] < 0 ) d[u][v] += MOD;
    					if ( d[v][u] < 0 ) d[v][u] += MOD;
    				}
    			}
    		}
    		ans = ( ans + ( ( bit & 1 ) ^ ( n & 1 ) ? det ( d ) : -det ( d ) ) ) % MOD;
    	}
    	printf ( "%d
    ", ( ans + MOD ) % MOD );
    	return 0;
    }
    
  • 相关阅读:
    微信小程序 改变radio(单选钮)默认大小
    iframe自适应高度
    微信小程序获得unionid
    Git的使用--如何将本地项目上传到Github
    一个服务器的Apache2.4.6配置多个域名
    CENTOS安装ElasticSearch
    CentOS7 64位下MySQL5.7安装与配置(YUM)
    在CentOS 7上搭建WordPress
    CentOS7安装MySQL
    Intellij idea 快捷键大全
  • 原文地址:https://www.cnblogs.com/rainybunny/p/13224105.html
Copyright © 2020-2023  润新知