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>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=5e4+5;
int n,m,hd[N],xnt,dfn[N],low[N],tim,fa[N],f[N],a[N<<1],q[N<<1],ans;//N<<1!!
struct Ed{
  int nxt,to;Ed(int n=0,int t=0):nxt(n),to(t) {}
}ed[N<<2];//<<2(?)
void add(int x,int y)
{
  ed[++xnt]=Ed(hd[x],y);hd[x]=xnt;
}
void dp(int x,int y)
{
  int m,i,l,r,p;
  for(m=0;y!=x;y=fa[y])a[++m]=f[y];// a is value
  for(a[++m]=f[x],i=1;i<m;i++)a[m+i]=a[i];// 2*m-1 is enough
  l=r=q[1]=1;p=(m>>1);
  for(i=2;i<=m+p;i++)
    {
      while(l<=r&&i-q[l]>p)l++;
      ans=max(ans,a[q[l]]+a[i]+i-q[l]);// a[],not f already(i is pos on a[])
      while(l<=r&&a[i]>=a[q[r]]+i-q[r])r--;
      q[++r]=i;
    }
  for(int i=1;i<m;i++)f[x]=max(f[x],a[i]+min(i,m-i));
}
void tarjan(int cr)
{
  dfn[cr]=low[cr]=++tim;
  for(int i=hd[cr],v;i;i=ed[i].nxt)
    if((v=ed[i].to)!=fa[cr])//!
      if(!dfn[v])
    {
      fa[v]=cr;tarjan(v);
      low[cr]=min(low[cr],low[v]);
      if(low[v]>dfn[cr])
        {
          ans=max(ans,f[cr]+f[v]+1);
          f[cr]=max(f[cr],f[v]+1);
        }
    }
      else low[cr]=min(low[cr],dfn[v]);
  for(int i=hd[cr],v;i;i=ed[i].nxt)
    if(fa[v=ed[i].to]!=cr&&dfn[v]>dfn[cr])dp(cr,v);
}
int main()
{
  scanf("%d%d",&n,&m);int k,x,y;
  for(int i=1;i<=m;i++)
    {
      scanf("%d%d",&k,&x);
      for(int j=1;j<k;j++)
    {
      scanf("%d",&y);
      add(x,y);add(y,x);x=y;
    }
    }
  tarjan(1);
  printf("%d",ans);
  return 0;
}

原文地址:https://www.cnblogs.com/Narh/p/9281201.html

时间: 2024-07-28 22:23:12

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

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仙人掌图(DP)

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

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】【SHOI2008】cactus仙人掌图

DP/仙人掌 题解:http://hzwer.com/4645.html->http://z55250825.blog.163.com/blog/static/150230809201412793151890/ QAQ了 呃……第一次做仙人掌的题目……感觉性质还是蛮神奇的(我是不是应该先做一点环套树的题目呢?>_>) 每个点都只会在一个简单环上,所以在dfs的时候,对于一个环,它上面的点是深度连续的一段(沿着father可以遍历这个环!),然后最后一个点再指回起始点,所以只要low改变了

【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千题计划113:bzoj1023: [SHOI2008]cactus仙人掌图

http://www.lydsy.com/JudgeOnline/problem.php?id=1023 dp[x] 表示以x为端点的最长链 子节点与x不在同一个环上,那就是两条最长半链长度 子节点与x在同一个环上,环形DP,单调队列优化 对于每一个环,深度最小的那个点 有可能会更新 上层节点, 所以 每一个环DP完之后,更新 dp[深度最小的点] #include<cstdio> #include<iostream> #include<algorithm> using

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

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+