码迷,mamicode.com
首页 > 其他好文 > 详细

[bzoj1023][SHOI2008]cactus 仙人掌图 (动态规划)

时间:2015-03-28 12:53:06      阅读:144      评论:0      收藏:0      [点我收藏+]

标签:

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

9

HINT

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


 技术分享

 

 TAT似乎是第一次写仙人掌类题目……刚开始一直再想“缩点dp缩点dp缩点dp”……结果发现多个环是可以共用一点的,缩点没法玩啊= =所以还是Link一下巨神们的题解吧= =

z55250825

ydc

 我自己模仿的很弱的实现:

技术分享
  1 /**************************************************************
  2     Problem: 1023
  3     User: AsmDef
  4     Language: C++
  5     Result: Accepted
  6     Time:408 ms
  7     Memory:8612 kb
  8 ****************************************************************/
  9  
 10 /***********************************************************************/
 11 /**********************By Asm.Def-Wu Jiaxin*****************************/
 12 /***********************************************************************/
 13 #include <cstdio>
 14 #include <cstring>
 15 #include <cstdlib>
 16 #include <ctime>
 17 #include <cctype>
 18 #include <algorithm>
 19 #include <cmath>
 20 using namespace std;
 21 #define getc() getchar()
 22 template<class T>inline void getd(T &x){
 23     char ch = getc();bool neg = false;
 24     while(!isdigit(ch) && ch != -)ch = getc();
 25     if(ch == -)ch = getc(), neg = true;
 26     x = ch - 0;
 27     while(isdigit(ch = getc()))x = x * 10 - 0 + ch;
 28     if(neg)x = -x;
 29 }
 30 /***********************************************************************/
 31 #include <vector>
 32 #include <queue>
 33 #define pb push_back
 34 #define pf push_front
 35 const int maxn = 50005;
 36 struct Edge{
 37     int u, v, top, size;
 38     void init(int a, int b){u = a, v = b;}
 39 }E[maxn * 3], *Eend = E;
 40 vector<Edge*>adj[maxn];
 41 Edge *Last[maxn];
 42 int dep[maxn], Ans, F[maxn], Stack[maxn], *Top = Stack;
 43 bool istop[maxn];
 44 struct Info{int val, id;Info(int a,int b){val = a, id = b;}};
 45  
 46 inline void RollDP(int size){
 47     int val[maxn<<1], N, i, mid = size >> 1, *it = val, Max = 0;
 48     deque<Info> Q;
 49     for(i = 0;i < size;++i)*it = F[Top[i]], Max = max(Max, min(i, size-i) + *(it++));
 50     for(i = 0;i < mid;++i)*(it++) = F[Top[i]];
 51     N = it - val;
 52     Ans = max(Ans, *val);
 53     Q.pb(Info(*val, 0));
 54     for(i = 1;i < N;++i){
 55         if(Q.front().id + mid < i)Q.pop_front();
 56         Ans = max(Ans, Q.front().val + val[i] + i);
 57         Info tmp(val[i]-i, i);
 58         while(!Q.empty() && Q.back().val <= tmp.val)Q.pop_back();
 59         Q.push_back(tmp);
 60     }
 61     F[*Top] = Max;
 62 }
 63  
 64 void dfs(int cur){
 65     static bool vis[maxn];vis[cur] = true;
 66     vector<Edge*>::iterator it;
 67     for(it = adj[cur].begin();it != adj[cur].end();++it){
 68         Edge &e = **it;
 69         if(Last[cur] && e.v == Last[cur]->u)continue;
 70         if(vis[e.v]){
 71             if(dep[e.v] > dep[cur])continue;
 72             Edge *t = &e;
 73             int top = e.v, s = dep[cur] - dep[top] + 1;
 74             do{
 75                 *(Top++) = t->v;
 76                 t->top = top, t->size = s;
 77                 t = Last[t->u];
 78             }while(t && t->v != top);
 79         }
 80         else{
 81             Last[e.v] = &e, dep[e.v] = dep[cur] + 1;
 82             dfs(e.v);
 83             if(!e.top){
 84                 Ans = max(Ans, F[cur] + F[e.v] + 1);
 85                 F[cur] = max(F[cur], F[e.v] + 1);
 86             }
 87             else if(e.top == cur){
 88                 while(*(--Top) != cur);
 89                 RollDP(e.size);
 90             }
 91         }
 92     }
 93 }
 94  
 95 inline void work(){
 96     int N, M, k, u, v;
 97     getd(N);getd(M);
 98     while(M--){
 99         getd(k);getd(v);
100         while(--k){
101             u = v;getd(v);
102             Eend->init(u, v);adj[u].pb(Eend++);
103             Eend->init(v, u);adj[v].pb(Eend++);
104         }
105     }
106     dfs(1);
107 }
108  
109  
110  
111 int main(){
112     work();
113     printf("%d\n", Ans);
114  
115 #ifdef DEBUG
116     printf("\n%.2lf sec \n", (double)clock() / CLOCKS_PER_SEC);
117 #endif
118     return 0;
119 }
120 ?
仙人掌dp

[bzoj1023][SHOI2008]cactus 仙人掌图 (动态规划)

标签:

原文地址:http://www.cnblogs.com/Asm-Definer/p/4373998.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!