P3349 [ZJOI2016]小星星
阿新 • • 發佈:2021-10-25
給定一個圖,和一棵樹,點數一樣,求把樹對映到圖上的方案。
可以想到用\(f[i][j][k]\)表示樹上i對映到圖上j,子樹集合為k的狀壓
要列舉子集,自己和每個兒子,還要遍歷一次樹
所以時間複雜度是\(O(n^3 \times 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, '\n'); 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, '\n'); return 0; } }
本文來自部落格園,作者:{2519},轉載請註明原文連結:https://www.cnblogs.com/QQ2519/p/15457332.html