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\n", 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

 

posted @ 2018-02-13 12:02  大财主  阅读(181)  评论(0编辑  收藏  举报