zoukankan      html  css  js  c++  java
  • LOJ#2723 多边形

    解:首先,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 }
    50分代码

    接下来说说K > 1的部分:

  • 相关阅读:
    AIMS 2013中的性能报告工具不能运行的解决办法
    读懂AIMS 2013中的性能分析报告
    在线研讨会网络视频讲座 方案设计利器Autodesk Infrastructure Modeler 2013
    Using New Profiling API to Analyze Performance of AIMS 2013
    Map 3D 2013 新功能和新API WebCast视频下载
    为Autodesk Infrastructure Map Server(AIMS) Mobile Viewer创建自定义控件
    ADN新开了云计算Cloud和移动计算Mobile相关技术的博客
    JavaScript修改css样式style
    文本编辑神器awk
    jquery 开发总结1
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10742757.html
Copyright © 2011-2022 走看看