解:首先,n<=20的直接暴力建图然后状压哈密顿回路,相信大家都会。固定1为起点,fi,s表示结尾为i点,状态为s。每次遍历i的出边转移,最后遍历1的出边统计答案。n22n。
然后就是正经题解了。先考虑K = 1的时候。对于一个子树,我们发现它只有三个地方有出边,左右上。而除此之外内部怎么连是没关系的,只要满足每个点都经过就行了。
于是就设fi,j表示以i为根的子树中,与外界连通状态为j的方案数。0表示从左右出去且经过根节点,1表示从左上出去,2表示从右上出去,3表示从左右出去且不经过根节点(这是为了方便转移才设的)。
每次合并两个子树而非一次做整个根节点(方便之后K > 1的时候),于是我们考虑每个状态如何被转移来:
- 0由所有子树中某两个相邻的12状态和两边的0状态转移来。也就是从0 + 0(前面有两个相邻的12)或1 + 2转移来。
- 1由最后的一个1和前面的所有0转移过来。也就是3 + 1。
- 2由最前面的一个2和后面的所有0转移过来,也就是2 + 0,注意要特判当前子树为第一个子树时的情况。
- 3由所有0转移过来,也就是0 + 0。
于是我们得到了一个O(n)的树形DP,注意根节点最后一个子树合并上来的时候,状态0还有一种情况就是最左2 + 中间0 + 最右1也就是2 + 1的转移。
然后输出f[1][0]即可获得30分,配合暴力有50分。
1 #include <bits/stdc++.h> 2 3 const int N = 1010, MO = 998244353; 4 5 struct Edge { 6 int nex, v; 7 }edge[N << 1]; int tp; 8 9 int e[N], n, K, fa[N], stk[N], top, pw[1200000]; 10 int f[22][1200000]; 11 std::vector<int> G[N]; 12 std::bitset<N> bt[N]; 13 14 inline void add(int x, int y) { 15 tp++; 16 //printf("add %d %d ", x, y); 17 bt[x].set(y); 18 edge[tp].v = y; 19 edge[tp].nex = e[x]; 20 e[x] = tp; 21 return; 22 } 23 24 void DFS(int x) { 25 if(!G[x].size()) { 26 stk[++top] = x; 27 } 28 for(int i = 0; i < (int)G[x].size(); i++) { 29 int y = G[x][i]; 30 DFS(y); 31 } 32 return; 33 } 34 35 inline void link(int x, int y) { 36 if(bt[x][y]) { 37 return; 38 } 39 add(x, y); 40 add(y, x); 41 return; 42 } 43 44 inline void out(int x) { 45 for(int i = 0; i < n; i++) { 46 printf("%d", (x >> i) & 1); 47 } 48 return; 49 } 50 51 namespace k1 { 52 int f[N][4]; 53 void DFS(int x) { 54 if(!G[x].size()) { 55 f[x][0] = f[x][1] = f[x][2] = 1; 56 //printf("x = %d %d %d %d %d ", x, f[x][0], f[x][1], f[x][2], f[x][3]); 57 return; 58 } 59 f[x][3] = 1; 60 for(int i = 0; i < G[x].size(); i++) { 61 int y = G[x][i]; 62 DFS(y); 63 ///merge 64 int t0 = (1ll * f[x][0] * f[y][0] % MO + 1ll * f[x][1] * f[y][2] % MO) % MO; 65 int t1 = 1ll * f[x][3] * f[y][1] % MO; 66 int t2 = i ? 1ll * f[x][2] * f[y][0] % MO : f[y][2]; 67 int t3 = 1ll * f[x][3] * f[y][0] % MO; 68 if(x == 1 && i == G[x].size() - 1) { 69 (t0 += 1ll * f[x][2] * f[y][1] % MO) %= MO; 70 } 71 f[x][0] = t0; 72 f[x][1] = t1; 73 f[x][2] = t2; 74 f[x][3] = t3; 75 } 76 //printf("x = %d %d %d %d %d ", x, f[x][0], f[x][1], f[x][2], f[x][3]); 77 return; 78 } 79 inline void solve() { 80 DFS(1); 81 printf("%d ", f[1][0]); 82 return; 83 } 84 } 85 86 int main() { 87 88 //freopen("polygon.in", "r", stdin); 89 //freopen("polygon.out", "w", stdout); 90 91 scanf("%d%d", &n, &K); 92 93 for(int i = 2, x; i <= n; i++) { 94 scanf("%d", &x); 95 add(x, i); add(i, x); 96 fa[i] = x; 97 G[x].push_back(i); 98 } 99 100 for(int i = 1; i <= n; i++) std::sort(G[i].begin(), G[i].end()); 101 102 if(K == 1) { 103 k1::solve(); 104 return 0; 105 } 106 107 DFS(1); 108 109 for(int i = 1; i <= top; i++) { 110 for(int j = 1; j <= K; j++) { 111 int temp = i + j; 112 if(temp > top) { 113 temp %= top; 114 } 115 if(!temp) { 116 temp = top; 117 } 118 link(stk[i], stk[temp]); 119 } 120 } 121 122 int lm = (1 << n); 123 for(int i = 2; i <= lm; i++) pw[i] = pw[i >> 1] + 1; 124 f[1][1] = 1; 125 for(int s = 1; s < lm; s++) { 126 for(int x = 1; x <= n; x++) { 127 /// f[x][s] 128 if(!f[x][s]) continue; 129 //printf("f %d ", x); out(s); printf(" = %d ", f[x][s]); 130 for(int i = e[x]; i; i = edge[i].nex) { 131 int y = edge[i].v; 132 if((s >> (y - 1)) & 1) { 133 continue; 134 } 135 (f[y][s | (1 << (y - 1))] += f[x][s]) %= MO; 136 } 137 } 138 } 139 int ans = 0; 140 for(int i = e[1]; i; i = edge[i].nex) { 141 int y = edge[i].v; 142 ans = (ans + f[y][lm - 1]) % MO; 143 } 144 printf("%lld ", 1ll * ans * (MO + 1) / 2 % MO); 145 return 0; 146 }
接下来说说K > 1的部分: