zoukankan      html  css  js  c++  java
  • 一些树上dp的复杂度证明

    以下均为内网

    树上染色 https://www.lydsy.com/JudgeOnline/problem.php?id=4033

    可怜与超市 http://hzoj.com/contest/62/problem/5

    可以简单的列出状态转移方程。

    它的转移过程类似:

     1 void dfs(int x)
     2 {
     3     for(unsigned i=0;i<p[x].size();++i) dfs(p[x][i]);
     4     int cur=0;
     5     memset(tmp[cur],0x3f,sizeof(tmp[cur]));
     6     tmp[cur][0][0]=tmp[cur][1][0]=0;
     7     for(unsigned i=0;i<p[x].size();++i)
     8     {
     9         int now=sz[p[x][i]]; cur^=1;
    10         memset(tmp[cur],0x3f,sizeof(tmp[cur]));
    11         for(int j=0;j<=sz[x];++j)
    12             for(int k=0;k<=now;++k)
    13             {
    14                 tmp[cur][1][k+j]=min(tmp[cur][1][k+j],tmp[cur^1][1][j]+dp[1][p[x][i]][k]);
    15                 tmp[cur][1][k+j]=min(tmp[cur][1][k+j],tmp[cur^1][1][j]+dp[0][p[x][i]][k]);
    16                 tmp[cur][0][k+j]=min(tmp[cur][0][k+j],tmp[cur^1][0][j]+dp[0][p[x][i]][k]);
    17             }
    18         sz[x]+=now;
    19     }
    20     ++sz[x];
    21     dp[0][x][0]=0; dp[1][x][0]=0;
    22     for(int i=1;i<=sz[x];++i) dp[1][x][i]=tmp[cur][1][i-1]+wc[x];//db(dp[1][x][i]);
    23     for(int i=1;i<=sz[x];++i) dp[0][x][i]=min(tmp[cur][0][i],tmp[cur][0][i-1]+c[x]);
    24 }
    eg

    看上去的复杂度是$O(n^3)$,

    然而仔细分析,复杂度只有$O(n^2)$,可以通过n为5000左右的数据。

    引入一个概念,(a,b)为树上的点对,则该点对在图中有$n^2$个

    观察状态的转移,

    在x节点范围内,设x有k个节点,

    复杂度为:

    $sum limits_{i=1}^{k}sum limits_{j=i}^{k}size_i*size_j$

    我们发现这样求出来,恰好是lca为x的点对个数。

    每个点对一定存在且仅存在一个lca,每个点对只会被统计不超过一次,

    所以总的复杂度为$O(n^2)$。

  • 相关阅读:
    vue路由跳转的方式(一)
    ElementUi树形目录
    Element UI问题总结
    angular入门
    IntelliJ IDEA 指定Java编译版本
    Python 笔记 v1
    Typora极简教程
    Gitbook在Windows上安装
    IntelliJ IDEA中查看UML类图
    服务器最大连接数问题
  • 原文地址:https://www.cnblogs.com/skyh/p/11191545.html
Copyright © 2011-2022 走看看