zoukankan      html  css  js  c++  java
  • BZOJ 1023: [SHOI2008]cactus仙人掌图 | 在仙人掌上跑DP

    题目:

    求仙人掌直径

    http://www.lydsy.com/JudgeOnline/problem.php?id=1023


    题解:

    首先给出仙人掌的定义:满足所有的边至多在一个环上的无向联通图

    我们先考虑一下如何求一棵树的直径

    1.维护以每个节点的为根的子树中,以根为一条路径端点的最长路和次长路,

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define N 50005
    using namespace std;
    inline int read()
    {
        int ret=0,neg=1;char j=getchar();
        for (;j>'9' || j<'0';j=getchar()) if (j=='-') neg=-1;
        for (;j>='0' && j<='9';j=getchar()) ret=ret*10+j-'0';
        return ret*neg;
    }
    int n,m,ecnt,ind,ans;
    int head[N],deep[N],f[N],low[N],dfn[N],fa[N];
    int a[2*N],q[2*N],l,r;
    struct adj{int v,nxt;}e[40*N];
    void add(int u,int v)
    {
        e[++ecnt].v=v;e[ecnt].nxt=head[u];head[u]=ecnt;
        e[++ecnt].v=u;e[ecnt].nxt=head[v];head[v]=ecnt;
    }
    void dp(int root,int x)
    {
        int tot=deep[x]-deep[root]+1;
        for (int i=x;i!=root;i=fa[i])
        a[tot--]=f[i];
        a[tot]=f[root];
        tot=deep[x]-deep[root]+1;
        for (int i=1;i<=tot;i++) a[i+tot]=a[i];
        q[1]=1;l=r=1;
        for (int i=2;i<=2*tot;i++)
        {
        while (l<=r && i-q[l]>tot/2) l++;
        ans=max(ans,a[i]+i+a[q[l]]-q[l]);
        while (l<=r && a[q[r]]-q[r]<=a[i]-i) r--;
        q[++r]=i;
        }
        for (int i=2;i<=tot;i++)
        f[root]=max(f[root],a[i]+min(i-1,tot-i+1));
    }
    void dfs(int x)
    {
        low[x]=dfn[x]=++ind;
        for (int i=head[x],v;i;i=e[i].nxt)
        if (e[i].v!=fa[x])
        {
            if (!dfn[v=e[i].v])
            {
            fa[v]=x;deep[v]=deep[x]+1;
            dfs(v);
            low[x]=min(low[x],low[v]);
            }
            else low[x]=min(low[x],dfn[v]);
            if (dfn[x]<low[v])
            ans=max(ans,f[x]+f[v]+1),f[x]=max(f[x],f[v]+1);
        }
        for (int i=head[x],v;i;i=e[i].nxt)
        if (fa[v=e[i].v]!=x && dfn[x]<dfn[v])
            dp(x,v);
    }
    int main()
    {
        n=read();m=read();
        for (int i=1;i<=m;i++)
        {
        int k=read(),x=read();
        for (int i=2;i<=k;i++)
        {
            int y=read();add(x,y);x=y;
        }
        }
        dfs(1);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    灌溉 最小生成树
    queue的应用uva540
    大数相加
    对于jquery实现原理的浅谈
    div+CSS实现页面的布局要点记录
    spring注解注入的学习
    jsp内置对象学习记录
    web应用的乱码解决
    新发现:排序算法时间复杂度只有O(3n),命名为"wgw"排序法
    java编写的Http协议的多线程下载器
  • 原文地址:https://www.cnblogs.com/mrsheep/p/8241767.html
Copyright © 2011-2022 走看看