• P3349 [ZJOI2016]小星星


    给定一个图,和一棵树,点数一样,求把树映射到图上的方案。

    可以想到用(f[i][j][k])表示树上i映射到图上j,子树集合为k的状压
    要枚举子集,自己和每个儿子,还要遍历一次树
    所以时间复杂度是(O(n^3 imes 3^n))
    正解状压还没搞出来。咕咕

    const int N = 19;
    int n, m;
    namespace brute {
    	std::bitset<N> b[N], c[N];
    	int a[N];
    	std::map<std::pair<int, int>, int> mp;
    	int main() {
    		read(n);
    		read(m);
    		int x, y,ans(0);
    		rep(i, 1, m) {
    			read(x);
    			read(y);
    			b[x][y] = b[y][x] = 1;
    		}
    		rep(i, 2, n) {
    			read(x);
    			read(y);
    			mp[ {x, y}] = mp[ {y, x}] = 1;
    		}
    
    		rep(i, 1, n) {
    			a[i] = i;
    		}
    		do {
    			bool flag(1);
    			for(auto j : mp) {
    				auto t = j.first.second;
    				auto tt = j.first.first;
    				t = a[t];
    				tt = a[tt];
    				flag &= b[t][tt];
    				if(!flag) break;
    			}
    			ans += flag;
    		} while(std::next_permutation(a + 1, a + n + 1));
    		out(ans, '
    ');
    		return 0;
    	}
    }
    namespace solve1 {
    
    	int mx;
    	struct graph {
    		int head[N], tot, next[N * N << 1], ver[N * N << 1];
    		inline void add(int a, int b) {
    			ver[++tot] = b;
    			next[tot] = head[a];
    			head[a] = tot;
    		}
    	} G, C;
    	int f[N][N][1 << 19];
    	std::vector<int> sta[N];
    	int siz[N];
    	inline void dfs(int x, int fa) {
    		siz[x] = 1;
    		rep(i, 1, n) {
    			f[x][i][1 << (i - 1)] = 1;//初始化
    		}
    
    		repc(x) {
    			int y(C.ver[j]);
    			if(y == fa) continue;
    			dfs(y, x);
     
    			rep(id, 1, n) {//枚举x映射的点id
    				for(auto S : sta[siz[x]]) {
    					if( !((S >> (id - 1)) & 1))  continue;//所选的集合必须要有id
    					repg(id) {
    						int yy = G.ver[i];
    						if((S >> (yy - 1)) & 1) continue;//俩集合必须不交
    
    						for(auto K : sta[siz[y]]) {
    							if(S & K || !((K >> (yy - 1) ) ) ) continue;
    							f[x][id][S | K] += f[x][id][S] * f[y][yy][K];//合成
    						}
    					}
    				}
    			}
    			siz[x] += siz[y];
    		}
    	}
    
    
    	int main() {
    		read(n);
    		read(m);
    
    		mx = (1 << n) - 1;
    
    		int x, y;
    		rep(i, 1, m) {
    			read(x);
    			read(y);
    			G.add(x, y);
    			G.add(y, x);
    		}
    
    		rep(i, 2, n) {
    			read(x);
    			read(y);
    			C.add(x, y);
    			C.add(y, x);
    		}
    
    		rep(i, 0, mx) {
    			int x = __builtin_popcount(i);
    			sta[x].push_back(i);
    		}
    
    		dfs(1, 0);
    		__int128 ans(0);
    		rep(i, 1, n) {
    			ans += f[1][i][mx];
    		}
    		out(ans, '
    ');
    		return 0;
    	}
    }
    

    本文来自博客园,作者:{2519},转载请注明原文链接:https://www.cnblogs.com/QQ2519/p/15457332.html

  • 相关阅读:
    xna 添加一个精灵1
    【leetcode】705. 设计哈希集合
    【leetcode】1603. 设计停车系统
    【leetcode】设计有序流
    【leetcode】旅行终点站
    【leetcode】检测大写字母
    【leetcode】重复至少 K 次且长度为 M 的模式
    【leetcode】二叉树的直径
    【leetcode】公交站间的距离
    【leetcode】分糖果
  • 原文地址:https://www.cnblogs.com/QQ2519/p/15457332.html
Copyright © 2020-2023  润新知