zoukankan      html  css  js  c++  java
  • ARC101E

    题目链接

    ARC101E - Ribbons on Tree

    题解

    令边集(S subseteq E)(f(S))为边集S中没有边被染色的方案数
    容斥一下,那么(ans = sum_{S subseteq E} (-1)^{ | S| f(S) })
    那么如何求对于原边集的(f(S)),也就是把(S)集合中的边全部删掉之后的各联通块内匹配的乘积
    (g(x))为大小为x的联通块内点两两匹配的方案
    那么(f(S)=prod_{i=1}^{|S|+1}g(a_i))
    考虑如何求ans
    (dp[i][j])表示以i为跟的子树中,有j各点没有在子树种匹配(链接到父节点
    转移背包一下
    对于(j=0)的时候由于那么i节点到父亲的边是没有覆盖的,容斥系数要取反
    那么
    $ f[i][0]=sum_{j=1}^{sz[i]}-1 imes f[i][j] imes g(j) $

    代码

    
    #include<cstdio> 
    #include<cstring> 
    #include<algorithm> 
    #define rep(p,x,k) for(int p = x;p <= k;++ p) 
    #define per(p,x,k) for(int p = x;p >= k;-- p) 
    #define gc getchar()
    #define pc putchar 
    #define LL long long  
    #define int long long
    inline LL read() {
        LL x = 0,f = 1; 
        char c = gc; 
        while(c < '0' || c > '9') c = gc; 
        while(c <= '9' && c >= '0') x = x * 10 + c -'0',c = gc; 
        return x ; 
    } 
    void print(LL x) { 
        if(x < 0) { 
            pc('-'); 
            x = -x; 
        } 
        if(x >= 10) print(x / 10); 
        pc(x % 10 + '0'); 
    } 
    const int maxn = 5007; 
    const int mod = 1e9 + 7; 
    int a[maxn]; 
    int n; 
    struct node { 
    	int v,next; 
    } edge[maxn << 1]; 
    int num = 0,head[maxn]; 
    inline void add_edge(int u,int v) {
    	edge[++ num].v = v; edge[num].next = head[u];head[u] = num; 
    } 
    int g[maxn]; 
    int dp[maxn][maxn]; 
    int siz[maxn]; 
    void dfs(int x,int fa) { 
    	static int t[maxn]; 
    	dp[x][1] = 1; siz[x] = 1; 
    	for(int i = head[x];i;i = edge[i].next) { 
    		int v = edge[i].v;  
    		if(v == fa) continue; 
    		dfs(v,x); 	
    		for(int j = 0,kel = siz[v];j <= siz[x];++ j) {
    			for(int k = 0;k <= siz[v];++ k) { 
    				(t[j + k] += 1ll * dp[x][j] * dp[v][k] % mod) %= mod; 
    			} 
    		} 
    		siz[x] += siz[v]; 
    		for(int j = 0;j <= siz[x];++ j) dp[x][j] = t[j],t[j] = 0; 
    	} 
    	LL sum = 0; 
    	for(int i = 0;i <= siz[x];i += 2) sum += mod - 1ll * dp[x][i] * g[i] % mod;
    	dp[x][0] = sum % mod; 
    } 
     main() { 
    	n = read(); 
    	int u,v; 
    	rep(i, 1,n - 1) { 
    		u = read(),v = read(); 
    		add_edge(u,v); 
    		add_edge(v,u); 
    	} 
    	g[0] = 1; 
    	for(int i = 2;i <= n;i += 2) (g[i] = 1ll * g[i - 2] * (i - 1)) %= mod;  
    	dfs(1,1);  
    	print((mod - dp[1][0]) % mod); 
    	return 0; 
    } 
    /*
    4
    1 2
    1 3
    1 4 
    */
    
    
  • 相关阅读:
    Python 学习日记 第七天
    Python 学习日记 第六天
    Python 学习日记 第五天
    Python 学习日记 第四天
    Redis 中的数据类型及基本操作
    Asp.net mvc 中View 的呈现(二)
    Asp.net mvc 中View的呈现(一)
    Asp.net mvc 中Action 方法的执行(三)
    Asp.net mvc 中Action 方法的执行(二)
    Asp.net mvc 中Action 方法的执行(一)
  • 原文地址:https://www.cnblogs.com/sssy/p/9800703.html
Copyright © 2011-2022 走看看