传送门


求仙人掌的直径,可以由求树的直径进行拓展,只需要在环上特殊判断。

沿用求树的直径的DP,对于一条不在任何环内的边,直接像树的直径一样转移,然后考虑环的影响。

设环长为\(cir\),在\(dfs\)树上,环对应的链的链顶为\(top\),链底为\(bot\),也就是说返祖边为\((top,bot)\),点\(x\)在\(dfs\)树上的深度为\(dep_x\)。

在统计环上的点之间的转移和贡献之前,先把环上所有点的子仙人掌的贡献统计好。

环上的转移直接通过方程式\(dp_{top} \leftarrow dp_{u} + \min\{dep_u - dep_{top} , cir - dep_u + dep_{top}\}\)从所有点转移到链顶

考虑如何统计环上的贡献,相对来说是比较难的一部分。

对于在环上的两个点\(u,v(dep_u > dep_v)\),它们对答案的贡献为\(dp_u + dp_v + \min\{dep_u - dep_{v} , cir - dep_u + dep_{v}\}\)

我们考虑将\(dp_u +dp_v + dep_u - dep_v\)和\(dp_u + dp_v + cir + dep_v - dep_u\)的贡献分开计算。下面只说\(dp_u + dp_v + dep_u - dep_v\)的情况,另一种计算同理。

我们考虑按照深度从大往小加点,那么如果对于两个点\(i,j\)满足\(dep_i < dep_j \&\& dep_i + dp_i \geq dep_j + dp_j\),表示\(i\)相比于\(j\)能够对更多的点产生贡献,而且转移更优,那么\(j\)就是没有必要的了。可以发现转移满足单调队列优化的性质,使用单调队列优化转移即可。记得转移需要满足\(dep_u - dep_v < cir + dep_v - dep_u\),如果队首不满足这个条件需要删除。

#include<bits/stdc++.h>
//This code is written by Itst
using namespace std;

inline int read(){
    int a = 0;
    char c = getchar();
    bool f = 0;
    while(!isdigit(c) && c != EOF){
        if(c == '-')
            f = 1;
        c = getchar();
    }
    if(c == EOF)
        exit(0);
    while(isdigit(c)){
        a = a * 10 + c - 48;
        c = getchar();
    }
    return f ? -a : a;
}

const int MAXN = 1e5 + 10;
struct Edge{
    int end , upEd;
}Ed[MAXN << 2];
int head[MAXN] , dp[MAXN] , dep[MAXN] , fa[MAXN] , ch[MAXN];
int N , M , cntEd , ans;
deque < int > q;

inline void addEd(int a , int b){
    Ed[++cntEd].end = b;
    Ed[cntEd].upEd = head[a];
    head[a] = cntEd;
}

void calc(int top , int bot){
    int cir = dep[bot] - dep[top] + 1 , p = bot;
    q.push_back(bot);
    do{
        ch[fa[p]] = p;
        p = fa[p];
        int t = q.front();
        if(dep[t] - dep[p] > cir - dep[t] + dep[p]){
            q.pop_front();
            t = q.front();
        }
        ans = max(ans , dep[t] - dep[p] + dp[t] + dp[p]);
        while(!q.empty() && dep[q.back()] + dp[q.back()] <= dep[p] + dp[p])
            q.pop_back();
        q.push_back(p);
    }while(p != top);
    q.clear();
    int p1 = top;
    p = bot;
    q.push_back(p1);
    while(cir - dep[p] + dep[top] <= dep[p] - dep[top])
        p = fa[p];
    do{
        p1 = ch[p1];
        p = ch[p];
        int t = q.front();
        ans = max(ans , cir + dep[t] - dep[p] + dp[t] + dp[p]);
        while(!q.empty() && dep[q.back()] + dp[q.back()] <= dep[p1] + dp[p1])
            q.pop_back();
        q.push_back(p1);
    }while(p != bot);
    q.clear();
    p = bot;
    while(p != top){
        dp[top] = max(dp[top] , dp[p] + min(dep[p] - dep[top] , cir + dep[top] - dep[p]));
        p = fa[p];
    }
}

int dfs(int x , int p){
    fa[x] = p;
    dep[x] = dep[p] + 1;
    int t = 0;
    for(int i = head[x] ; i ; i = Ed[i].upEd)
        if(Ed[i].end != p)
            if(dep[Ed[i].end])
                if(dep[Ed[i].end] < dep[x])
                    t = Ed[i].end;
                else
                    calc(x , Ed[i].end);
            else{
                int q = dfs(Ed[i].end , x);
                if(!q){
                    ans = max(ans , dp[x] + dp[Ed[i].end] + 1);
                    dp[x] = max(dp[x] , dp[Ed[i].end] + 1);
                }
                else
                    if(q != x)
                        t = q;
            }
    return t;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
    //freopen("out","w",stdout);
#endif
    N = read();
    M = read();
    for(int i = 1 ; i <= M ; ++i){
        int L = read() , a = read();
        for(int i = 2 ; i <= L ; ++i){
            int b = read();
            addEd(a , b);
            addEd(b , a);
            a = b;
        }
    }
    dfs(1 , 0);
    cout << ans;
    return 0;
}

BZOJ1023 SHOI2008 仙人掌图 仙人掌、单调队列的更多相关文章

  1. 1023: [SHOI2008]cactus仙人掌图(DP+单调队列优化)

    这道题吗= =首先解决了我多年以来对仙人掌图的疑问,原来这种高大上的东西原来是这个啊= = 然后,看到这种题,首先必须的就是缩点= = 缩点完之后呢,变成在树上找最长路了= =直接树形dp了 那么那些 ...

  2. BZOJ1023: [SHOI2008]cactus仙人掌图(仙人掌dp)

    Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3467  Solved: 1438[Submit][Status][Discuss] Descripti ...

  3. BZOJ1023: [SHOI2008]cactus仙人掌图(仙人掌)

    Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的 ...

  4. BZOJ1023:[SHOI2008]cactus仙人掌图(圆方树,DP,单调队列)

    Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌图(cactus). 所谓简单回路就是指在图上不重复经过任何一个顶点 ...

  5. 2018.10.29 bzoj1023: [SHOI2008]cactus仙人掌图(仙人掌+单调队列优化dp)

    传送门 求仙人掌的直径. 感觉不是很难. 分点在环上面和不在环上分类讨论. 不在环上直接树形dpdpdp. 然后如果在环上讨论一波. 首先对环的祖先有贡献的只有环上dfsdfsdfs序最小的点. 对答 ...

  6. bzoj 1023: [SHOI2008]cactus仙人掌图 tarjan缩环&&环上单调队列

    1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1141  Solved: 435[Submit][ ...

  7. bzoj 1023: [SHOI2008]cactus仙人掌图【tarjan+dp+单调队列】

    本来想先求出点双再一个一个处理结果写了很长发现太麻烦 设f[u]为u点向下的最长链 就是再tarjan的过程中,先照常处理,用最长儿子链和次长儿子链更新按ans,然后处理以这个点为根的环,也就是这个点 ...

  8. bzoj千题计划113:bzoj1023: [SHOI2008]cactus仙人掌图

    http://www.lydsy.com/JudgeOnline/problem.php?id=1023 dp[x] 表示以x为端点的最长链 子节点与x不在同一个环上,那就是两条最长半链长度 子节点与 ...

  9. bzoj1023: [SHOI2008]cactus仙人掌图

    学习了一下圆方树. 圆方树是一种可以处理仙人掌的数据结构,具体见这里:http://immortalco.blog.uoj.ac/blog/1955 简单来讲它是这么做的:用tarjan找环,然后对每 ...

随机推荐

  1. iTools(pro)下载

    http://bbs.feng.com/forum.php?mod=viewthread&tid=10225990&page=1&extra=#pid157941878 htt ...

  2. (后端)swagger

    Swagger 文档提供了一个方法,使我们可以用指定的 JSON 或者 YAML 摘要来描述你的 API,包括了比如 names.order 等 API 信息. 你可以通过一个文本编辑器来编辑 Swa ...

  3. win10 出现0x80072efd错误

    0x80072efd 0x80072efd 是网络问题,windows更新或windows应用商店出现0x80072efd问题,请检查本机代理,是否开着小飞机(Shadowsocks)之类的代理工具. ...

  4. jdk各版本特性

    JDK Version 1.0 开发代号为Oak(橡树),于1996-01-23发行. JDK Version 1.1 于1997-02-19发行. 引入的新特性包括: 引入JDBC(Java Dat ...

  5. web前端(10)—— 浮动,清除默认样式

    文档流 web页面和ps等设计软件有本质的区别,web 网页的制作,是个“流”,从上而下 ,像 “织毛衣”,就跟编程语言一样,都是由上而下 而设计软件 ,想往哪里画东西,就去哪里画 文档流带来的最明显 ...

  6. php防范

    针对 PHP 的网站主要存在下面几种攻击方式: 1.命令注入(Command Injection) 2.eval 注入(Eval Injection) 3.客户端脚本攻击(Script Inserti ...

  7. Spring的事务管理1

    事务的回顾: 事务:逻辑上的一组操作,组成这组事务的各个单元,要么全部成功,要么全部失败 事务的特性:ACID 原子性(Atomicity):事务不可分割 一致性(Consistency):事务执行前 ...

  8. wangedit

    <template> <el-row id="AddRoom"> <el-col :span="5">.</el-co ...

  9. 用js显示系统当前日期

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  10. linux学习笔记整理(三)

    第四章 文件的基本管理和XFS文件系统备份恢复本节所讲内容:4.1 Linux系统目录结构和相对/绝对路径.4.2 创建/复制/删除文件,rm -rf / 意外事故4.3 查看文件内容的命令4.4 实 ...