• bzoj 1023[SHOI2008]cactus仙人掌图


    1023: [SHOI2008]cactus仙人掌图

    Time Limit: 1 Sec  Memory Limit: 162 MB

    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。


     

    毒瘤仙人掌

    关于仙人掌的学习可以参考WC2017 cjk 大神的课件

    http://immortalco.blog.uoj.ac/blog/1955

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #define LL long long
      7 
      8 using namespace std;
      9 
     10 const int MAXN = 1e6 + 10;
     11 int N, M;
     12 int u, v, w;
     13 int ans = 0;
     14 int cnt = 0;
     15 int num = 0;
     16 int hd = 0, tail = 0;
     17 int head[MAXN], head2[MAXN];
     18 int from[MAXN];
     19 int len[MAXN];
     20 int q[MAXN];
     21 int fa[MAXN];
     22 int dfn[MAXN], low[MAXN];
     23 int dis[MAXN];
     24 int flag[MAXN];
     25 int dp[MAXN];
     26 inline LL read()
     27 {
     28     LL x = 0, w = 1; char ch = 0;
     29     while(ch < '0' || ch > '9') {
     30         if(ch == '-') {
     31             w = -1;
     32         }
     33         ch = getchar();
     34     }
     35     while(ch >= '0' && ch <= '9') {
     36         x = x * 10 + ch - '0';
     37         ch = getchar();
     38     }
     39     return x * w;
     40 }
     41 struct edge {
     42     int v;
     43     int next;
     44     int w;
     45 } g[MAXN], gg[MAXN];
     46 
     47 void addedge(int u, int v, int w)
     48 {
     49     g[++cnt].v = v;
     50     g[cnt].w = w;
     51     g[cnt].next = head[u];
     52     head[u] = cnt;
     53 }
     54 
     55 void addedge2(int u, int v, int w)
     56 {
     57     gg[++cnt].v = v;
     58     gg[cnt].w = w;
     59     gg[cnt].next = head2[u];
     60     head2[u] = cnt;
     61 }
     62 void tarjan(int x)
     63 {
     64 //    cout<<x<<endl;
     65     dfn[x] = ++cnt;
     66     for(int j = head[x]; j; j = g[j].next) {
     67         int to = g[j].v;
     68         if(fa[x] != to) {
     69             if(dfn[to] == 0) {
     70                 fa[to] = x;
     71                 dis[to] = dis[x] + 1;
     72                 tarjan(to);                
     73             } else if(dfn[to] < dfn[x]){
     74                 N++;
     75                 flag[N] = 1;
     76                 from[N] = ++num;
     77                 addedge2(to, N, 0);
     78                 int tmp = x;
     79                 len[num] = dis[x] - dis[to] + 1;
     80                 int tot = 0;
     81                 while(tmp != to) {
     82                     tot++;
     83                     addedge2(N, tmp, min(dis[tmp] - dis[to], len[num] - (dis[tmp] - dis[to])));
     84                     from[tmp] = num;
     85                     tmp = fa[tmp]; 
     86                 }
     87             }
     88         }
     89     }
     90     if(from[x] == 0) {
     91         addedge2(fa[x], x, 1);
     92     }
     93 }
     94 void DFS(int x)
     95 {
     96     int fir = 0, sec = 0;
     97     for(int j = head2[x]; j; j = gg[j].next) {
     98         int to = gg[j].v;
     99             DFS(to);
    100             if(dp[to] + gg[j].w > sec) {
    101                 sec = dp[to] + gg[j].w;
    102             }
    103             if(sec > fir) {
    104                 swap(sec, fir);
    105             }
    106     }
    107     dp[x] = fir;
    108     if(!flag[x]) {
    109         ans = max(ans, fir + sec);
    110     } else {
    111         hd = 0, tail = 0;
    112         int b = from[x], mx = -1e9;
    113         for(int j = head2[x]; j; j = gg[j].next) {
    114             int to = gg[j].v;
    115             while(hd < tail && dis[to] - dis[q[hd]] > len[b] / 2) {
    116                 mx = max(mx, dp[q[hd]] + len[b] + dis[q[hd]]);
    117                 hd++;
    118             }
    119             ans = max(ans, mx + dp[to] - dis[to]);
    120             if(hd < tail) {
    121                 ans = max(ans, dp[q[hd]] - dis[q[hd]] + dp[to] + dis[to]);
    122             }
    123             while(tail > hd && dp[to] - dis[to] > dp[q[tail - 1]] - dis[q[tail - 1]]) {
    124                 tail--;
    125             }
    126             q[tail++] = to;
    127         }
    128     }
    129 }
    130 int main()
    131 {
    132     N = read(), M = read();
    133     for(int i = 1; i <= M; i++) {
    134         int k = read();
    135         u = read();
    136         for(int j = 1; j < k; j++) {
    137             v = read();
    138             addedge(u, v, 1);
    139             addedge(v, u, 1);
    140             u = v;
    141         }
    142     }
    143     cnt = 0;
    144     tarjan(1);
    145     DFS(1);
    146     /*for(int i = 1; i <= N; i++) {
    147         cout<<i<<" "<<dp[i]<<endl;
    148     }
    149     cout<<endl;*/
    150     printf("%d
    ", ans);
    151     return 0;
    152 }
    153 
    154 /*
    155 15 3
    156 
    157 9 1 2 3 4 5 6 7 8 3
    158 
    159 7 2 9 10 11 12 13 10
    160 
    161 5 2 14 9 15 10
    162 
    163 */
    View Code
  • 相关阅读:
    flask2 未整理
    flask1 未整理
    libvirt创建kvm虚拟机步骤
    libvirt之 virsh命令总结
    kvm的xml文件解释
    virsh命令和调用libvirt api的区别
    KVM
    libvirt
    kvm
    oracle中正则表达式的使用
  • 原文地址:https://www.cnblogs.com/wuenze/p/8446393.html
Copyright © 2020-2023  润新知