zoukankan      html  css  js  c++  java
  • 【ZJOI2016】小星星 容斥+树形DP

    题意

    UOJ #185.
    给出一个(n(n le 17)) 的树和 (n) 个点的图,求有多少种树点和图点的对应方案是“好的”
    “好的”方案,如果现在树上两点间存在边,那么要求图上对应的这两点之间也有边。

    题解

    考虑用 (dp) 去计算方案数,如果需要确定一个顺序来dp,显然是从叶子向上树形dp。
    不妨设 1 为整棵树的根,现在用 (f_{i, j}) 表示树上一颗以 (i) 为根的子树全部确定对应点,(i) 树点对应 (j) 图点。

    [f_{u, i} = prod_v (sum_j f_{v, j}) ]

    但这样计算有一个问题,会有多个树点选择了同一个图点,会算重。
    这时注意到 (n) 非常小,因此可以容斥。
    状态为(1) 的图点可以选择,其他不能。然后每个状态计算一下,最后统计就好。

    总的来说就是先容斥再每个状态都树形DP。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    #define mp make_pair
    typedef long long ll;
    const int N = 18;
    int n, m, cnt, id[N];
    int e, to[N << 1], nxt[N << 1], hd[N];
    ll f[N][N];
    bool ed[N][N];
    void add(int u, int v){
    	to[++e] = v; nxt[e] = hd[u]; hd[u] = e;
    }
    void dfs(int u, int fa){
    	for(int i = hd[u]; i; i = nxt[i]){
    		int v = to[i]; if(v == fa) continue;
    		dfs(v, u);
    	}
    	for(int i = 1; i <= cnt; i++){
    		f[u][i] = 1;
    		for(int j = hd[u]; j; j = nxt[j]){
    			int v = to[j]; if(v == fa) continue;
    			ll sum = 0;
    			for(int k = 1; k <= cnt; k++)
    				if(ed[id[i]][id[k]]) sum += f[v][k];
    			f[u][i] *= sum;
    		}
    	}//树形DP
    	return;
    }
    int main(){
    	scanf("%d%d", &n, &m);
    	for(int i = 1, u, v; i <= m; i++)
    		scanf("%d%d", &u, &v), ed[u][v] = ed[v][u] = 1;
    	for(int i = 1, u, v; i < n; i++)
    		scanf("%d%d", &u, &v), add(u, v), add(v, u);
    	ll ans = 0;
    	for(int i = 0; i < (1 << n); i++){
    		cnt = 0;
    		for(int j = 1; j <= n; j++)
    			if(i & (1 << (j - 1)))
    				id[++cnt] = j;
    		dfs(1, 0);
    		ll sum = 0;
    		for(int j = 1; j <= cnt; j++)
    			sum += f[1][j];
    		ans += (((cnt ^ n) & 1) ? -1 : 1) * sum;
    	}//容斥
    	printf("%lld
    ", ans);
    	return 0;
    }
    
    qaqaq
  • 相关阅读:
    手机端局部滚动问题 overflow-y:auto|scroll无效,使用iscroll解决
    h5 js 图片预览并判断 ajax上传
    安装一些包管理的记录 win10
    nginx php rewrite配置
    记一次u盘 无法格式化、0字节、写保护的解决过程
    erlang,elixir安装
    Redis详解:lists数据类型及操作
    redis类型[string 、list 、 set 、sorted set 、hash]
    java 生成Word文档
    mysql 获取当前月最后一天和第一天
  • 原文地址:https://www.cnblogs.com/zdsrs060330/p/14927139.html
Copyright © 2011-2022 走看看