BZOJ 1023

program bzoj1023;
uses math;

const inf=1000000000;
    maxn=50005;
    maxm=20000005;

type edge=record
    togo,next:longint;
end;

var n,m,cnt,ind,ans,l,r:longint;
    last,deep,f,low,dfn,fa:array [0..maxn] of longint;
    a,q:array [0..maxn*2] of longint;
    e:array [0..maxm] of edge;

procedure insert(u,v:longint);
begin
  inc(cnt);
  e[cnt].togo:=v; e[cnt].next:=last[u]; last[u]:=cnt;
  inc(cnt);
  e[cnt].togo:=u; e[cnt].next:=last[v]; last[v]:=cnt;
end;

procedure dp(root,x:longint);
var tot,i:longint;
begin
    tot:=deep[x]-deep[root]+1;
    i:=x;
    while i<>root do
        begin
            a[tot]:=f[i];
            dec(tot);
            i:=fa[i];
        end;
    a[tot]:=f[root];
    tot:=deep[x]-deep[root]+1;
    for i:=1 to tot do
        a[i+tot]:=a[i];
    q[1]:=1; l:=1; r:=1;
    for i:=2 to (tot shl 1) do
        begin
            while (l<=r) and (i-q[l]>(tot shr 1)) do
            inc(l);
            ans:=max(ans,a[i]+i+a[q[l]]-q[l]);
            while (l<=r) and (a[q[r]]-q[r]<=a[i]-i) do
                dec(r);
            inc(r);
            q[r]:=i;
        end;
    for i:=2 to tot do
    f[tot]:=max(f[root],a[i]+min(i-1,tot-i+1));
end;

procedure dfs(x:longint);
var i:longint;
begin
    inc(ind);
    low[x]:=ind;
    dfn[x]:=ind;
    i:=last[x];
    while i<>0 do
        begin
          if e[i].togo<>fa[x] then
            begin
                if dfn[e[i].togo]=0 then
                    begin
                        fa[e[i].togo]:=x;
                        deep[e[i].togo]:=deep[x]+1;
                        dfs(e[i].togo);
                        low[x]:=min(low[x],low[e[i].togo]);
                    end
                else
                    low[x]:=min(low[x],dfn[e[i].togo]);
                if dfn[x]<low[e[i].togo] then
                    begin
                      ans:=max(ans,f[x]+f[e[i].togo]+1);
                      f[x]:=max(f[x],f[e[i].togo]+1);
                    end;
            end;
          i:=e[i].next;
        end;
    i:=last[x];
    while i<>0 do
        begin
          if (fa[e[i].togo]<>x) and (dfn[x]<dfn[e[i].togo]) then
          dp(x,e[i].togo);
          i:=e[i].next;
        end;
end;

procedure main;
var i,j,a,b,k:longint;
begin
    read(n,m);
    for i:=1 to m do
        begin
            read(k,a);
            for j:=2 to k do
            begin
                read(b);
                insert(a,b);
                a:=b;
            end;
        end;
    dfs(1);
    writeln(ans);
end;

begin
      main;
end.
时间: 2024-08-24 22:22:05

BZOJ 1023的相关文章

bzoj 1023: [SHOI2008]cactus仙人掌图 tarjan索环&amp;&amp;环上单调队列

1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1141  Solved: 435[Submit][Status] Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的回路. 举例来说,上面的第一个例子是一张仙人图,而第二个不是——注意到它有三条简单回路

bzoj 1023: [SHOI2008]cactus仙人掌图 2125: 最短路 4728: 挪威的森林 静态仙人掌上路径长度的维护系列

%%% http://immortalco.blog.uoj.ac/blog/1955 一个通用的写法是建树,对每个环建一个新点,去掉环上的边,原先环上每个点到新点连边,边权为点到环根的最短/长路长度 1023 求仙人掌直径 树形dp,维护每个点向下的最长和次长路径长度,对原有的点直接更新答案,对新点可以把对应环上的点取出,倍长,破环成链,并用单调队列正反各扫一次 #include<cstdio> char buf[5000000],*ptr=buf-1; int _(){ int x=0,c

【BZOJ 1023】 [SHOI2008]cactus仙人掌图

1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 1235  Solved: 482 [Submit][Status] Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的回路. 举例来说,上面的第一个例子是一张仙人图,而第二个不是--注意到它有三条简单

bzoj 1023 [SHOI2008]cactus仙人掌图 ( poj 3567 Cactus Reloaded )——仙人掌直径模板

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1023 http://poj.org/problem?id=3567 因为lyd在讲课,所以有了lyd的模板.感觉人家写得好好呀!于是学习(抄)了一下.可以记一记. 反正各种优美.那个dp断环成链的地方那么流畅自然!tarjan里的那些 if 条件那么美! 不过十分不明白为什么边要开成4倍的.开成2倍的真的会RE.怎么分析仙人掌的边数? #include<iostream> #includ

bzoj 1023 仙人掌图

Description 求一个仙人掌图的直径 Solution 仙人掌图有个性质,一条边要么是割边要么就是在环内,那么我们可以对它进行Dp辣! 令f[u]表示以u为根的子树最长链长度 如果u?v是桥的话转移就是ans=max(ans,f[u]+f[v]+1),f[u]=max(f[u],f[v]+1),因为当前f[u]都是由它的孩子更新来的 如果是环的话,变环为链,用单调队列dp出ans,然后用环上的f值更新f[u]的值就可以了,具体实现见代码 Code #include <bits/stdc+

bzoj 1023: [SHOI2008]cactus仙人掌图

这个题真的不会啊 简而言之就是树形DP+环形Dp 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<queue> 7 #include<algorithm> 8 #include<vector> 9 #define M 50008 10 #def

【BZOJ 1023】【SHOI 2008】cactus仙人掌图

良心的题解↓ http://z55250825.blog.163.com/blog/static/150230809201412793151890/ tarjan的时候如果是树边则做树形DP(遇到环就无视),最后在tarjan回溯前扫一遍当前点为“最高点”的环,进行环上DP,这个环上DP是$O(n^2)$的,但如果我们用单调队列优化则是$O(n×2)$的 总复杂度$O(n)$真是无限仰膜OTZ #include<cstdio> #include<cstring> #include&

BZOJ.1023.[SHOI2008]cactus仙人掌图(DP)

题目链接 类似求树的直径,可以用(类似)树形DP求每个点其子树(在仙人掌上就是诱导子图)最长链.次长链,用每个点子节点不同子树的 max{最长链}+max{次长链} 更新答案.(不需要存次长链,求解过程中先更新ans,然后再更新最长链即可) 设f[i]为点i的诱导子图中最长链的长度. 对于环,我们找一个环上dep[]最小的点x代表这个环 看做一个点(dep为按DFS顺序更新的),求出f[x],环以外的部分像树一样直接做就可以. 对于环的处理:f[x]比较显然,f[x]=max{f[v]+dis(

[树形dp][Tarjan][单调队列] Bzoj 1023 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)同时出现在前两 个的简单回路里.另外,第三张图也不是仙人图,因为它并不是连通图