zoukankan      html  css  js  c++  java
  • [ZJOI2016]小星星

    /*
    给定一张n点m边无向图以及n个点的树
    求将n个点一一映射到图上,并且本来两个点之间有连边的点现在依然有连边 求方案数
    
    根据定义状态压缩有一个N^3 * 3^n的算法, f[i][j][S]表示以i为根, 根对应到图中是j, 在图中已经匹配的状态为S的方案数
    
    然后我们对他进行容斥优化
    
    现在我们 考虑标号可以重复的情况, 那么最终答案等于 没有限制的 - 1个图中点强制不能填的 + 2个图中点强制不能填的 - ....
    
    然后我们可以枚举2 ^ n种限制状态, 然后在强制不选择这些的情况 带上容斥系数计算即可
    
    注意要卡卡常数
    */
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #include<cmath>
    #define ll long long
    #define M 17
    #define mmp make_pair
    using namespace std;
    int read() {
    	int nm = 0, f = 1;
    	char c = getchar();
    	for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    	return nm * f;
    }
    vector<int>to[M];
    int note[M][M], sta[M], tp, n, m, poww[1 << M];
    ll f[M][M], ans;
    
    void dp(int now, int fa) {
    	for(int i = 0; i < tp; i++) f[now][i] = 1;
    	for(int j = 0; j < to[now].size(); j++) {
    		int vj = to[now][j];
    		if(vj == fa) continue;
    		dp(vj, now);
    		for(int i = 0; i < tp; i++) {
    			ll t = 0;
    			for(int k = 0; k < tp; k++) {
    				if(note[sta[i]][sta[k]]) t += f[vj][k];
    			}
    			f[now][i] *= t;
    		}
    	}
    }
    
    int main() {
    	n = read(), m = read();
    	for(int i = 1; i <= m; i++) {
    		int vi = read() - 1, vj = read() - 1;
    		note[vi][vj] = note[vj][vi] = 1;
    	}
    	for(int i = 1; i < n; i++) {
    		int vi = read() - 1, vj = read() - 1;
    		to[vi].push_back(vj);
    		to[vj].push_back(vi);
    	}
    	if(n & 1) poww[0] = -1;
    	else poww[0] = 1;
    	for(int s = 1; s < (1 << n); s++) {
    		poww[s] = -poww[s - (s & -s)];
    		tp = 0;
    		for(int i = 0; i < n; i++) {
    			if(s & (1 << i)) sta[tp++] = i;
    		}
    		//	memset(f, 0, sizeof(f));
    		dp(0, 0);
    		for(int i = 0; i < tp; i++) ans += f[0][i] * poww[s];
    	}
    	cout << ans << "
    ";
    	return 0;
    }
    
    
  • 相关阅读:
    bzoj 1176 cdq分治套树状数组
    Codeforces 669E cdq分治
    Codeforces 1101D 点分治
    Codeforces 1100E 拓扑排序
    Codeforces 1188D Make Equal DP
    Codeforces 1188A 构造
    Codeforces 1188B 式子转化
    Codeforces 1188C DP 鸽巢原理
    Codeforces 1179D 树形DP 斜率优化
    git commit -m "XX"报错 pre -commit hook failed (add --no-verify to bypass)问题
  • 原文地址:https://www.cnblogs.com/luoyibujue/p/10507202.html
Copyright © 2011-2022 走看看