zoukankan      html  css  js  c++  java
  • BZOJ1023: [SHOI2008]cactus仙人掌图(仙人掌)

    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

    Sample Output

    8
     
    解题思路
     
    第一次接触仙人掌的蒟蒻QAQ
    今天本来想学一下圆方树,然而还没学到怎么建就卡在了这道题上。
    这是一道仙人掌入门题,思路也比较朴素。
    对于一颗仙人掌,我们最不容易处理的就是环,对于一个环,我们视为一个点双连通分量。
    所以我们使用tarjan
    因为一个不在环内的点和环的顶点都可以直接更新答案。
    答案用最长路径+子节点最长路径+1更新。
    这个点的最长路径用子节点最长路径+1更新。
    注意顺序!
    在一个环的顶点将整个环抽出(因为是一个环,所以抽出后复制一遍成为一个两倍的链)
    然后DP就可以啦
    最长路径可以被中间链+子节点最长路径更新
    这部分需要使用单调队列维护
    最后更新顶点即可^_^
      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 struct pnt{
      6     int hd;
      7     int fa;
      8     int dfn;
      9     int low;
     10     int mxc;
     11 }p[1000000];
     12 struct ent{
     13     int twd;
     14     int lst;
     15 }e[1000000];
     16 int cnt;
     17 int n,m,k;
     18 int trc;
     19 int ans;
     20 int crt;
     21 int crl[1000000];
     22 int q[1000000];
     23 int h,t;
     24 void ade(int f,int t)
     25 {
     26     cnt++;
     27     e[cnt].twd=t;
     28     e[cnt].lst=p[f].hd;
     29     p[f].hd=cnt;
     30 }
     31 void ringbrk(int st,int fi)
     32 {
     33     crt=0;
     34     while(fi!=st)
     35     {
     36         crl[++crt]=p[fi].mxc;
     37         fi=p[fi].fa;
     38     }
     39     crl[++crt]=p[st].mxc;
     40     for(int i=1;i<crt;i++)
     41         crl[crt+i]=crl[i];
     42     h=t=1;
     43     q[1]=1;
     44     int ln=crt/2;
     45     for(int i=2;i<=crt+ln;i++)
     46     {
     47         while(h<=t&&i-q[h]>ln)
     48             h++;
     49         ans=max(ans,crl[q[h]]+crl[i]+i-q[h]);
     50         while(h<=t&&crl[q[t]]+i-q[t]<=crl[i])
     51             t--;
     52         q[++t]=i;
     53     }
     54     for(int i=1;i<crt;i++)
     55     {
     56         p[st].mxc=max(p[st].mxc,crl[i]+min(i,crt-i));
     57     }
     58 }
     59 void tarjan(int x)
     60 {
     61     p[x].dfn=p[x].low=++trc;
     62     for(int i=p[x].hd;i;i=e[i].lst)
     63     {
     64         int to=e[i].twd;
     65         if(to==p[x].fa)continue;
     66         if(!p[to].dfn)
     67         {
     68             p[to].fa=x;
     69             tarjan(to);
     70             p[x].low=min(p[x].low,p[to].low);
     71             if(p[x].dfn<p[to].low)
     72             {
     73                 ans=max(ans,p[x].mxc+p[to].mxc+1);
     74                 p[x].mxc=max(p[x].mxc,p[to].mxc+1);
     75             }
     76         }else{
     77             p[x].low=min(p[x].low,p[to].low);
     78         }
     79     }
     80     for(int i=p[x].hd;i;i=e[i].lst)
     81     {
     82         int to=e[i].twd;
     83         if(p[to].fa!=x&&p[to].dfn>p[x].dfn)
     84         {
     85             ringbrk(x,to);
     86         }
     87     }
     88 }
     89 int main()
     90 {
     91     scanf("%d%d",&n,&m);
     92     for(int i=1;i<=m;i++)
     93     {
     94         int frm,twd,nm;
     95         scanf("%d%d",&nm,&frm);
     96         for(int j=1;j<nm;j++)
     97         {
     98             scanf("%d",&twd);
     99             ade(twd,frm);
    100             ade(frm,twd);
    101             frm=twd;
    102         }
    103     }
    104     tarjan(1);
    105     printf("%d
    ",ans);
    106     return 0;
    107 }
  • 相关阅读:
    AtCoder Beginner Contest 205
    Codeforces Round #725 (Div. 3)
    Educational Codeforces Round 110 (Rated for Div. 2)【A
    Codeforces Round #722 (Div. 2)
    AtCoder Beginner Contest 203(Sponsored by Panasonic)
    AISing Programming Contest 2021(AtCoder Beginner Contest 202)
    PTA 520 钻石争霸赛 2021
    Educational Codeforces Round 109 (Rated for Div. 2)【ABCD】
    AtCoder Beginner Contest 200 E
    Educational Codeforces Round 108 (Rated for Div. 2)【ABCD】
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9460665.html
Copyright © 2011-2022 走看看