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
    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 ", Ans);
    114  
    115 #ifdef DEBUG
    116     printf(" %.2lf sec  ", (double)clock() / CLOCKS_PER_SEC);
    117 #endif
    118     return 0;
    119 }
    120 
    仙人掌dp

  • 相关阅读:
    在集群环境中使用 EhCache 缓存系统|RMI 集群模式
    oracle中的针对该库的表
    oracle:触发器,自治事务 trigger
    PL/SQL中查询某的时间段内所有执行的sql
    金额input框控制只能小数点后有两位的有效数字
    JS判断键盘上的上下左右键
    MySQL按照汉字的拼音排序
    JAVA经典总结
    普通for循环遍历LinkedList弊端
    EASYUI 1.4版 combobox firefox 下不支持中文检索的问题
  • 原文地址:https://www.cnblogs.com/Asm-Definer/p/4373998.html
Copyright © 2011-2022 走看看