zoukankan      html  css  js  c++  java
  • 虚树学习

    口胡一下怕忘了。应该会有错留坑回来改。

    例题:bzoj2286: [Sdoi2011]消耗战 

    哔哔一下题意:边有边权。$m$次询问,每次给定$k$个点,割掉若干条边使得$1$号点与给定的点不连通,要求代价最小。

    $n leq 2e5 , sum k leq 5e5$

    首先这个$sum k$就很特别。是建虚树的契机。

    我们不可能每次跑一遍$O(n)$的树$dp$,那我们能不能每次$O(k)$呢?

    做法就是每回只在关键点上做$dp$,就要求我们建出只有关键点的树。即虚树。注意关键点不仅是给定的$k$个点,还有它们所有点两两的LCA。

    实际上算上LCA也只有不超过$2k$个点。想一想为什么。(没事,我自己想想而已)

    靠全是废话。直接说咋构建。

    所有点按dfs序排序。按顺序插入栈中。设栈顶元素为$p$,现在要插入$x$。

    栈里维护的是根到$p$的一条链。每插入一个点,和栈顶只有两种关系:

    $p$和$x$的LCA是$p$;是另一个点(可能在栈里可能不在,可能是给定点可能不是)。根据dfs序,不存在第三种情况。

    第一种情况,直接进栈,注意不用加边。因为可能会出现和之后点的LCA在$p$之下,这种情况下应该是$p$连这个LCA,LCA再连$x$。而这时候这个LCA还不知道是谁甚至有没有。

    另一种情况,我们令$LCA(p,x)$为$fa$。这时说明$p$的子树已经遍历完了,不然不会轮到$x$。我们前面说过这个$fa$可在可不在,但一定在栈当前维护的链上。(真tm废话)于是开始弹栈。

    我们称栈顶的第二个元素为$q$,如果$q$的深度(这里用dfs序也是一样的道理)大于$fa$,$fa$在$q$之上,$p$与$q$连边,弹出$q$。直到$q$的深度等于或者小于$fa$的,说明$q$就是$fa$或者$fa$在$p,q$之间,$fa,p$连边,$fa$入栈,$p$弹栈(要是$fa=q$就不用了),$x$入栈。

    所有点对的LCA我们可以$O(logn)$时间求出,所以所有询问构建虚树的总复杂度就是$O(sum k logn)$的。听着高大上的东西,其实道理很简单。给我的感觉就是和缩点的$tarjan$算法一样,只是一个工具,难点还是在于$dp$吧。

    板子等我熟练了在贴吧。。


    upd

    可能就是这样吧 

    s[++top]=1;
    for(int i=(a[1]==1)+1;i<=k;i++){
        int f=lca(a[i],s[top]);
        if(f==s[top]){
            s[++top]=a[i];continue;
        }
        while(1){
            if(dep[s[top-1]]<=dep[f]){
                add(f,s[top]);
                top--;
                if(s[top]^f)s[++top]=f;
                break;
            }
            add(s[top],s[top-1]);
            top--;
        }
        s[++top]=a[i];
    }
    while(--top)add(s[top],s[top+1]);
  • 相关阅读:
    Linux记录-shell实现脚本监控服务器及web应用
    Hadoop记录-hadoop和hbase监控有那些比较好的工具
    Hadoop记录-Ganglia监控HDFS和HBase指标说明
    Linux记录-CPU指标介绍
    Linux记录-I/O系统监控
    Linux记录-linux系统监控命令汇总
    Hadoop记录-hadoop2.x常用端口及定义方法
    Linux记录-linux系统常用监控指标
    在IIS6上部署WebService
    《软件测试自动化之道》读书笔记 之 请求-响应测试
  • 原文地址:https://www.cnblogs.com/orzzz/p/8232344.html
Copyright © 2011-2022 走看看