zoukankan      html  css  js  c++  java
  • Luogu4244 [SHOI2008]仙人掌图 II

    Luogu4244 [SHOI2008]仙人掌图 II

    传送门

    Luogu

    题解

    题目要求的是仙人掌的直径,考虑在圆方树上(dp),等价于对于(f_u)表示(u)子树内的最长链的长度.

    如果是圆点之间的连边,直接转移即可.

    如果是一个环之间的转移,可以将转移系数赋到这个环的环顶上面.

    一个环的转移,等同于是枚举环上面的点然后走这个点到顶的最短距离.

    一个环的贡献,等同于是枚举两个点计算贡献,这个可以用单调队列维护.

    代码

    快读写错调了1h.

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<queue>
    #include<iostream>
    #include<set>
    #include<map>
    using namespace std;
    #define mp make_pair
    #define ll long long
    #define re register
    typedef pair<int,int> pii;
    #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    inline int gi()
    {
    	int f=1,sum=0;char ch=getchar();
    	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    	return f*sum;
    }
    const int N=400010;
    int n,m,front[N],cnt,f[N],fa[N],low[N],dfn[N],Time,ans=1,dep[N],top,q[N],sta[N];
    struct node{int to,nxt;}e[N<<1];
    void Add(int u,int v){e[++cnt]=(node){v,front[u]};front[u]=cnt;}
    void solve(int u,int v)
    {
    	int tot=0;
    	for(int i=v;i!=u;i=fa[i])sta[++tot]=i;sta[++tot]=u;
    	reverse(sta+1,sta+tot+1);
    	for(int i=1;i<=tot;i++)sta[i+tot]=sta[i];
    	int H=1,T=0;
    	for(int i=1;i<=tot+tot;i++)
    	{
    		while(H<=T&&i-q[H]>tot/2)H++;
    		if(H<=T)ans=max(ans,f[sta[i]]+f[sta[q[H]]]+i-q[H]);
    		while(H<=T&&f[sta[i]]-i>f[sta[q[T]]]-q[T])T--;q[++T]=i;
    	}
    	for(int i=v;i!=u;i=fa[i])
    		f[u]=max(f[u],f[i]+min(dep[i]-dep[u],dep[v]-dep[i]+1));
    	for(int i=1;i<=tot+tot;i++)sta[i]=0,q[i]=0;
    }
    void dfs(int u,int ff)
    {
    	dfn[u]=low[u]=++Time;fa[u]=ff;dep[u]=dep[ff]+1;
    	for(int i=front[u];i;i=e[i].nxt)
    	{
    		int v=e[i].to;if(v==ff)continue;
    		if(!dfn[v]){dfs(v,u);low[u]=min(low[u],low[v]);}
    		else low[u]=min(low[u],dfn[v]);
    		if(dfn[u]<low[v]){ans=max(ans,f[u]+f[v]+1);f[u]=max(f[u],f[v]+1);}
    	}
    	for(int i=front[u];i;i=e[i].nxt)
    	{
    		int v=e[i].to;if(v==ff)continue;
    		if(fa[v]!=u&&dfn[u]<dfn[v])solve(u,v);
    	}
    }
    int main()
    {
    	n=gi();int k=gi();
    	while(k--)
    	{
    		int p=gi()-1,u=gi();
    		for(int i=1;i<=p;i++)
    		{
    			int v=gi();
    			if(u){Add(u,v);Add(v,u);}
    			u=v;
    		}
    	}
    	dfs(1,0);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    HyperV创建NAT网络
    Win10
    ConEmu
    ffmpeg的centos、msys2、msvc编译
    7z压缩gopath的src的批处理
    VS2015自带v120的Platform Toolset
    Putty配置
    第一章:HTML5的基础
    java的错题整理
    第十四章:类的带参方法
  • 原文地址:https://www.cnblogs.com/fexuile/p/13025456.html
Copyright © 2011-2022 走看看