• bzoj1023: [SHOI2008]cactus仙人掌图


    学习了一下圆方树。

    圆方树是一种可以处理仙人掌的数据结构,具体见这里:http://immortalco.blog.uoj.ac/blog/1955

    简单来讲它是这么做的:用tarjan找环,然后对每个环建立一个新点,然后将环上的边删去,并环上的每个点都连到新点上。这样我们就可以把一个环缩成一个菊花图,重复这么做,一棵仙人掌就变成一棵树啦!这棵树就叫做圆方树,其中原点叫圆点,新点叫方点。

    圆方树和原仙人掌很相似,而且它又是一棵树,于是我们就可以在上面dp啦!不过要注意的是对于方点的处理,不能直接更新,要作一个单调队列,因为环上有两种走法么。

    期间调了很久,而且我还不会生成数据,orz cbh。

    tarjan求DCC都不会写了,我好弱啊~

    #include <bits/stdc++.h>
    #define N 110000
    using namespace std;
    int n, m, nn;
    vector <int> V[N], W[N];
    int low[N], dfn[N], dfsnum;
    int f[N];
    int ans;
    int shed[N], top;
    deque <int> Q;
    void tarjan(int t, int f)
    {
        dfn[t] = low[t] = ++ dfsnum;
        shed[++ top] = t;
        for (int p = 0; p < V[t].size(); ++ p)
            if (V[t][p] != f) if (!dfn[V[t][p]])
            {
                tarjan(V[t][p], t);
                low[t] = min(low[t], low[V[t][p]]);
                if (low[V[t][p]] >= dfn[t])
                {
                    if (shed[top] != V[t][p])
                    {
                        nn ++;
                        int cur;
                        do
                        {
                            //W[shed[top]].push_back(nn);
                            W[nn].push_back(cur = shed[top]);
                            shed[top --] = 0;
                        }
                        while (cur != V[t][p]);
                        W[t].push_back(nn);
                        //W[nn].push_back(t);
                    }
                    else
                    {
                        W[t].push_back(shed[top]);
                        //W[shed[top]].push_back(t);
                        shed[top --] = 0;
                    }
                }
            }
            else low[t] = min(low[t], dfn[V[t][p]]);
    }
    void dfs(int t)
    {
        f[t] = 0;
        int s = W[t].size();
        if (t > n)
        {
            for (int p = 0; p < s; ++ p)
                dfs(W[t][p]);
            for (int q = 0; q < (s + 1) / 2; ++ q)
            {
                while (!Q.empty() && f[W[t][Q.back()]] + Q.back() < f[W[t][q]] + q) Q.pop_back();
                Q.push_back(q);
            }
            for (int p = 0, q = (s + 1) / 2; p < s; ++ p, q = (q == s? 0: q + 1) )
            {
                if (q != s)
                {
                    while (!Q.empty() && f[W[t][Q.back()]] + (Q.back() < p? Q.back() + s + 1 - p: Q.back() - p) < f[W[t][q]] + (q < p? q + s + 1 - p: q - p)) Q.pop_back();
                    Q.push_back(q);
                }
                if (Q.front() == p) Q.pop_front();
                if (!Q.empty()) ans = max(ans, f[W[t][p]] + f[W[t][Q.front()]] + (Q.front() > p? Q.front() - p: Q.front() + s + 1 - p));
            }
            for (int p = 0; p < (s + 1) / 2; ++ p) f[t] = max(f[t], f[W[t][p]] + p);
            for (int p = (s + 1) / 2; p < s; ++ p) f[t] = max(f[t], f[W[t][p]] + s - 1 - p);
            Q.clear();
        }
        else
        {
            int mx1 = 0, mx2 = 0;
            for (int p = 0; p < s; ++ p)
            {
                dfs(W[t][p]);
                if (f[W[t][p]] + 1 > mx1) mx2 = mx1, mx1 = f[W[t][p]] + 1;
                else if (f[W[t][p]] + 1 > mx2) mx2 = f[W[t][p]] + 1;
            }
            ans = max(ans, mx1 + mx2);
            f[t] = mx1;
        }
    }
    int main()
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= m; ++ i)
        {
            int k, a;
            scanf("%d%d", &k, &a);
            for (int i = 2; i <= k; ++ i)
            {
                int b;
                scanf("%d", &b);
                V[a].push_back(b);
                V[b].push_back(a);
                a = b;
            }
        }
        nn = n;
        tarjan(1, 0);
        //puts("haha");
        dfs(1);
        printf("%d
    ", ans);
    }
  • 相关阅读:
    关于selenium中的三种等待方式与EC模块的知识
    re.findall用法
    链表及链表的逆置
    通过两个队列实现一个栈
    flask与Django框架的区别
    http协议与https协议
    Maven系列教材 (四)- 通过命令行创建Maven风格的Java项目
    Maven系列教材 (三)- 仓库概念,下载与配置
    Maven系列教材 (二)- 下载与配置Maven
    Maven系列教材 (一)- 什么是Maven
  • 原文地址:https://www.cnblogs.com/AwD-/p/5735108.html
Copyright © 2020-2023  润新知