zoukankan      html  css  js  c++  java
  • 【BZOJ 4455】【UOJ #185】【ZJOI 2016】小星星

    http://www.lydsy.com/JudgeOnline/problem.php?id=4455

    http://uoj.ac/problem/185

    有一个$O(n^n)$的暴力,放宽限制可以转化成$O(2^n)$的容斥,容斥每一层统计用$O(n^3)$的dp来统计。时间复杂度$O(n^3 2^n)$。

    卡常!存图用邻接表!减小非递归函数的使用,尽量写到主函数里!

    最后终于卡过了QwQ

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 20;
    int in() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = (k << 3) + (k << 1) + c - '0';
    	return k * fh;
    }
    
    
    ll f[N][N];
    bool mp[N][N];
    struct node {int nxt, to;} T[N << 1];
    int pointT[N], cntT = 0, n, m, fa[N], use[N], usenum;
    
    void insT(int u, int v) {T[++cntT] = (node) {pointT[u], v}, pointT[u] = cntT;}
    
    void mkfa(int x) {
    	for(int i = pointT[x]; i; i = T[i].nxt)
    		if (T[i].to != fa[x]) {
    			fa[T[i].to] = x;
    			mkfa(T[i].to);
    		}
    }
    
    ll cal(int x, int y) {
    	ll mul = 1, ret; int v;
    	for(int i = pointT[x]; i; i = T[i].nxt)
    		if ((v = T[i].to) != fa[x]) {
    			ret = 0;
    			for(int j = 1; j <= usenum; ++j)
    				if (mp[y][use[j]]) ret += f[v][use[j]];
    			mul *= ret;
    		}
    	return mul;
    }
    
    void dfs(int x) {
    	for(int i = pointT[x]; i; i = T[i].nxt)
    		if (T[i].to != fa[x]) dfs(T[i].to);
    	
    	for(int i = 1; i <= usenum; ++i)
    		f[x][use[i]] = cal(x, use[i]);
    }
    
    int main() {
    	n = in(); m = in();
    	int u, v;
    	for(int i = 1; i <= m; ++i) {
    		u = in(); v = in();
    		mp[u][v] = mp[v][u] = true;
    	}
    	for(int i = 1; i < n; ++i) {
    		u = in(); v = in();
    		insT(u, v); insT(v, u);
    	}
    	
    	fa[1] = 0; mkfa(1);
    	
    	int tot = (1 << n) - 1, mu = n & 1;
    	ll ret, ans = 0;
    	for(int i = 1; i <= tot; ++i) {
    		usenum = 0;
    		for(int j = 0; j < n; ++j)
    			if ((1 << j) & i) use[++usenum] = j + 1;
    		
    		dfs(1);
    		ret = 0;
    		for(int i = 1; i <= usenum; ++i)
    			ret += f[1][use[i]];
    		if ((usenum & 1) == mu) ans += ret;
    		else ans -= ret;
    	}
    	
    	printf("%lld
    ", ans);
    	return 0;
    }
  • 相关阅读:
    Demo学习: DownloadDemo
    Demo学习: FileUpload
    Demo学习: Dialogs Anonymous Callback
    Demo学习: Cookies Demo
    Demo学习: CustomException
    Demo学习: Collapsible Panels
    Demo学习: ColumnSort
    Demo学习: ClientInfo
    Demo学习: Closable Tabs
    Demo学习: ClientEvents
  • 原文地址:https://www.cnblogs.com/abclzr/p/5777908.html
Copyright © 2011-2022 走看看