P4244 [SHOI2008]仙人掌图 II

P4244 [SHOI2008]仙人掌图 II

仙人掌求直径,和树一样最大+次大
处理环时,算一下环内两点距离+子树最大和,根节点此时的其他子树已确定的最大子树 用 环内一点距离+点最大子树更新

#include
#include
#include
#include
using namespace std;
typedef long long LL;
const LL maxn=1e7;
inline LL Read(){
    LL x=0,f=1; char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1; c=getchar();
    }
    while(c>='0'&&c<='9')
        x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return x*f;
}
struct node{
    LL to,next;
}dis[maxn];
LL n,m,num,ans,tot;
LL dp[maxn],dep[maxn],low[maxn],dfn[maxn],a[maxn],head[maxn],fa[maxn],q[maxn];
inline void Add(LL u,LL v){
    dis[++num]=(node){v,head[u]},head[u]=num;
}
inline void Dp(LL u,LL v){
    LL len=dep[v]-dep[u]+1,j=len;
    for(int i=v;i!=u;i=fa[i])
        a[j--]=dp[i]; a[j]=dp[u];
    for(LL i=1;i<=len;++i)
        a[i+len]=a[i];
    LL hea=1,tail=1; 
    q[1]=1;
    for(LL i=2;i<=len*2;++i){
        while(hea<=tail&&i-q[hea]>len/2) 
            hea++;
        ans=max(ans,a[i]+i+a[q[hea]]-q[hea]);
        while(hea<=tail&&a[q[tail]]-q[tail]dfn[u]){
            ans=max(ans,dp[u]+dp[v]+1);
            dp[u]=max(dp[u],dp[v]+1);
        }
    }
    for(LL i=head[u];i;i=dis[i].next){
        LL v=dis[i].to;
        if(fa[v]!=u&&dfn[u]

转载于:https://www.cnblogs.com/y2823774827y/p/10201005.html

你可能感兴趣的:(P4244 [SHOI2008]仙人掌图 II)