题解:http://hzwer.com/4645.html->http://z55250825.blog.163.com/blog/static/150230809201412793151890/

  QAQ了

  呃……第一次做仙人掌的题目……感觉性质还是蛮神奇的(我是不是应该先做一点环套树的题目呢?>_>)

  每个点都只会在一个简单环上,所以在dfs的时候,对于一个环,它上面的点是深度连续的一段(沿着father可以遍历这个环!),然后最后一个点再指回起始点,所以只要low改变了,就找到了一个环。。。

  判是否在环上也很好判,看下low就可以了

  简单了解了仙人掌的情况,我们来看下这道题怎么做:

  如果是一棵树的话,我们只要Tree DP就可以了……令f[i]表示以 i 为根的最长的链,子树合并的时候随便搞搞……比较简单。

  现在麻烦的是出现了环= =所以f[i]的定义本身就有些纠结……

  既然这样,那么我们就把问题分成两部分来做吧!树的部分和环的部分!

  对于树的部分……同上【BZOJ】【1023】【SHOI2008】cactus仙人掌图

  那么环的部分是什么情况呢?我们可以令f[i]表示环上这个点向外的最长链的长度(这个定义对于树的部分不冲突,所以不用分开算)然后环上的最长链就是:$ans=max\{ f[i]+f[j]+min\{j-i,tot-j+i\} \}$呃……其实意思就是找环上两条链出来,然后加上它俩直接的距离求个最大值。最后需要更新一下环的“根”节点的f[root],这时它的子树已经完全计算完毕了,那么f[root]就应该表示以它为根的最长链,那么我们就可以用环上其他点连出去的链来更新这个f[root](其实之前算环上两条链的时候有一种情况算不到,现在就是在做这个哦,这句如果不理解就忽视掉吧,不是很重要……)

 1 /**************************************************************
 2     Problem: 1023
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:212 ms
 7     Memory:9792 kb
 8 ****************************************************************/
 9  
10 //BZOJ 1023
11 #include<cstdio>
12 #include<cstring>
13 #include<cstdlib>
14 #include<iostream>
15 #include<algorithm>
16 #define rep(i,n) for(int i=0;i<n;++i)
17 #define F(i,j,n) for(int i=j;i<=n;++i)
18 #define D(i,j,n) for(int i=j;i>=n;--i)
19 using namespace std;
20 typedef long long LL;
21 inline int getint(){
22     int v=0,r=1; char ch=getchar();
23     for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-1;
24     for(; isdigit(ch);ch=getchar()) v=v*10+ch-'0';
25     return v*r;
26 }
27 const int N=1e5+10,INF=~0u>>2;
28 /*********************template******************/
29 int to[N<<2],next[N<<2],head[N],cnt;
30 void add(int x,int y){
31     to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt;
32     to[++cnt]=x; next[cnt]=head[y]; head[y]=cnt;
33 }
34 int dfn[N],low[N],fa[N],dep[N],dfs_clock,a[N],Q[N],f[N];
35 int n,m,ans;
36 void dp(int root,int x){
37     int tot=dep[x]-dep[root]+1,j=tot;
38     for(int i=x;i!=root;i=fa[i])
39         a[j--]=f[i];
40     a[j]=f[root];
41     F(i,1,tot) a[i+tot]=a[i];
42     int l=0,r=-1;
43     Q[++r]=1;
44     F(i,2,tot*2){
45         while(l<=r && i-Q[l]>tot/2) l++;
46         ans=max(ans,a[i]+i+a[Q[l]]-Q[l]);
47         while(l<=r && a[Q[r]]-Q[r]<a[i]-i) r--;
48         Q[++r]=i;
49     }
50     F(i,2,tot)
51         f[root]=max(f[root],a[i]+min(i-1,tot-i+1));
52 }
53 void dfs(int x){
54     dfn[x]=low[x]=++dfs_clock;
55     for(int i=head[x];i;i=next[i])
56         if (to[i]!=fa[x]){
57             if (!dfn[to[i]]){
58                 fa[to[i]]=x;
59                 dep[to[i]]=dep[x]+1;
60                 dfs(to[i]);
61                 low[x]=min(low[x],low[to[i]]);
62             }else low[x]=min(low[x],dfn[to[i]]);
63             if (dfn[x]<low[to[i]]){
64                 ans=max(ans,f[x]+f[to[i]]+1);
65                 f[x]=max(f[x],f[to[i]]+1);
66             }
67         }
68     for(int i=head[x];i;i=next[i])
69         if (fa[to[i]]!=x && dfn[x]<dfn[to[i]])
70             dp(x,to[i]);
71 }
72 int main(){
73 #ifndef ONLINE_JUDGE
74     freopen("1023.in","r",stdin);
75     freopen("std.out","w",stdout);
76 #endif
77     n=getint(); m=getint();
78     F(i,1,m){
79         int k=getint(),a=getint(),b;
80         F(i,2,k){
81             b=getint();
82             add(a,b);
83             a=b;
84         }
85     }
86     dfs(1);
87     printf("%d\n",ans);
88     return 0;
89 }
View Code

相关文章:

  • 2021-06-02
  • 2022-12-23
  • 2021-04-28
  • 2021-10-20
  • 2021-10-17
  • 2021-11-26
  • 2021-06-09
猜你喜欢
  • 2021-11-30
  • 2021-12-31
  • 2021-09-19
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-18
相关资源
相似解决方案