题解: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]的定义本身就有些纠结……
既然这样,那么我们就把问题分成两部分来做吧!树的部分和环的部分!
对于树的部分……同上
那么环的部分是什么情况呢?我们可以令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 }