zoukankan      html  css  js  c++  java
  • bzoj千题计划113:bzoj1023: [SHOI2008]cactus仙人掌图

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

    dp[x] 表示以x为端点的最长链

    子节点与x不在同一个环上,那就是两条最长半链长度

    子节点与x在同一个环上,环形DP,单调队列优化

    对于每一个环,深度最小的那个点 有可能会更新 上层节点,

    所以 每一个环DP完之后,更新 dp[深度最小的点]

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    #define N 500001
    
    int front[N],nxt[N<<2],to[N<<2],tot=1;
    
    int dfn[N],low[N],fa[N],dep[N];
    
    int dp[N],f[N],ans;
    
    int tmp[N<<1],q[N];
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    void add(int u,int v)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
    }
    
    void circular(int x,int y)
    {
        int cnt=dep[y]-dep[x]+1; int now=y;
        while(dfn[fa[now]]>=dfn[x]) tmp[cnt--]=now,now=fa[now];
        tmp[cnt]=now;
        cnt=dep[y]-dep[x]+1;
        int nn=cnt;
        for(int i=1;i<=cnt;++i) tmp[++nn]=tmp[i];
        int h=0,t=0;
        for(int i=1;i<=nn;++i)
        {
            while(h<t && i-q[h]>cnt/2) h++;
            if(h<t) ans=max(ans,dp[tmp[i]]+dp[tmp[q[h]]]+i-q[h]); 
            while(h<t && dp[tmp[i]]-i>dp[tmp[q[t-1]]]-q[t-1]) t--;
            q[t++]=i;
        }
        for(int i=2;i<=cnt;++i) dp[x]=max(dp[x],dp[tmp[i]]+min(i-1,cnt-i+1));
    }
    
    void tarjan(int x,int y)
    {
        low[x]=dfn[x]=++tot;
        for(int i=front[x];i;i=nxt[i])
        {
            if(i==(y^1)) continue;
            if(!dfn[to[i]]) 
            {
                fa[to[i]]=x;
                dep[to[i]]=dep[x]+1;
                tarjan(to[i],i);
                low[x]=min(low[x],low[to[i]]);
            }
            else low[x]=min(low[x],dfn[to[i]]);
            if(dfn[x]<low[to[i]])
            {
                ans=max(ans,dp[x]+dp[to[i]]+1);
                dp[x]=max(dp[x],dp[to[i]]+1);
            }
        }
        for(int i=front[x];i;i=nxt[i])
        {
            if(i==(y^1)) continue;
            if(fa[to[i]]!=x && dfn[x]<dfn[to[i]]) circular(x,to[i]);
        }
    }
    
    int main()
    {
        //freopen("bzoj_1023.in","r",stdin);
        //freopen("bzoj_1023.out","w",stdout);
        int n,m;
        read(n); read(m);
        int k,x,last;
        while(m--)
        {
            read(k); read(last);
            k--;
            while(k--) { read(x); add(x,last);    last=x;}
        }
        tot=0;
        tarjan(1,0);
        cout<<ans;
    }

    1023: [SHOI2008]cactus仙人掌图

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 2993  Solved: 1246
    [Submit][Status][Discuss]

    Description

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

     

      举例来说,上面的第一个例子是一张仙人图,而第二个不是——注意到它有三条简单回路:(4,3,2,1,6
    ,5,4)、(7,8,9,10,2,3,7)以及(4,3,7,8,9,10,2,1,6,5,4),而(2,3)同时出现在前两
    个的简单回路里。另外,第三张图也不是仙人图,因为它并不是连通图。显然,仙人图上的每条边,或者是这张仙
    人图的桥(bridge),或者在且仅在一个简单回路里,两者必居其一。定义在图上两点之间的距离为这两点之间最
    短路径的距离。定义一个图的直径为这张图相距最远的两个点的距离。现在我们假定仙人图的每条边的权值都是1
    ,你的任务是求出给定的仙人图的直径。

    Input

      输入的第一行包括两个整数n和m(1≤n≤50000以及0≤m≤10000)。其中n代表顶点个数,我们约定图中的顶
    点将从1到n编号。接下来一共有m行。代表m条路径。每行的开始有一个整数k(2≤k≤1000),代表在这条路径上
    的顶点个数。接下来是k个1到n之间的整数,分别对应了一个顶点,相邻的顶点表示存在一条连接这两个顶点的边
    。一条路径上可能通过一个顶点好几次,比如对于第一个样例,第一条路径从3经过8,又从8返回到了3,但是我们
    保证所有的边都会出现在某条路径上,而且不会重复出现在两条路径上,或者在一条路径上出现两次。

    Output

      只需输出一个数,这个数表示仙人图的直径长度。

    Sample Input

    15 3
    9 1 2 3 4 5 6 7 8 3
    7 2 9 10 11 12 13 10
    5 2 14 9 15 10 8
    10 1
    10 1 2 3 4 5 6 7 8 9 10

    Sample Output

    8
    9

    HINT

    对第一个样例的说明:如图,6号点和12号点的最短路径长度为8,所以这张图的直径为8。


     


    【注意】使用Pascal语言的选手请注意:你的程序在处理大数据的时候可能会出现栈溢出。

    如果需要调整栈空间的大小,可以在程序的开头填加一句:{$M 5000000},其中5000000即

    指代栈空间的大小,请根据自己的程序选择适当的数值。
  • 相关阅读:
    SQL Azure (17) SQL Azure V12
    Microsoft Azure News(5) Azure新DV2系列虚拟机上线
    Azure Redis Cache (3) 在Windows 环境下使用Redis Benchmark
    Azure PowerShell (11) 使用自定义虚拟机镜像模板,创建Azure虚拟机并绑定公网IP(VIP)和内网IP(DIP)
    Windows Azure Virtual Machine (31) 迁移Azure虚拟机
    Windows Azure Web Site (16) Azure Web Site HTTPS
    Azure China (12) 域名备案问题
    一分钟快速入门openstack
    管理员必备的Linux系统监控工具
    Keepalived+Nginx实现高可用和双主节点负载均衡
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7895298.html
Copyright © 2011-2022 走看看