• 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 }
  • 相关阅读:
    npm 发包流程
    iframe嵌入第三方视频链接自动播放
    微信小程序 接入腾讯地图的两种写法
    微信小程序 生命周期
    css 传送阵
    微信小程序 音频播放器
    微信小程序 mpvue 使用vant-weapp
    微信小程序 使用mpvue
    ajax
    布局问题
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9460665.html
Copyright © 2020-2023  润新知