ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

基环树的直径

2022-08-03 22:33:45  阅读:111  来源: 互联网

标签:ch const int ll long 基环树 maxn 直径


转载自LIOI_TEos的题解

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 1e6 + 100;
const ll mod = 20040820;
const int INF = 2147483647;
const int lim = 1e4 + 1;

int n, v[maxn], v2[maxn], r[maxn];
ll anss, st, ans2, ans3, cnt, dp[maxn<<1], s[maxn];//不知道题解上s数组为什么不开*2
ll ans, d[maxn];

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

struct node 
{
    int next, to;
    ll w;
}a[maxn<<1];
int head[maxn], len;

void add(int x, int y, ll w)
{
    a[++len].to = y; a[len].next = head[x]; a[len].w = w;
    head[x] = len;
}

bool dfs(int now, int la)
{
    if(v[now] == 1)
    {
        v[now] = 2; r[++cnt] = now; v2[now] = 1;
        return 1;
    }
    v[now] = 1;
    for(int i=head[now]; i; i=a[i].next)
    {
        if(i!=((la-1)^1)+1 && dfs(a[i].to, i))
        {
            if(v[now]!=2)
            {
                r[++cnt] = now; v2[now] = 1; s[cnt] = s[cnt-1]+a[i].w;
            }
            else 
            {
                s[st-1] = s[st]-a[i].w;//s[0]
                //需要这样来得到一个正确的值是因为上一次倍长后没有清空
                return 0;
            }
            return 1;
        }
    }
    return 0;
}

void tree_dp(int now)
{
    v2[now] = 1;
    for(int i=head[now]; i; i=a[i].next)
    {
        int y = a[i].to;
        if(v2[y]) continue;
        tree_dp(y);
        ans = max(ans, d[now]+d[y]+a[i].w);//以now为轴连接两条链
        d[now] = max(d[now], d[y]+a[i].w);//now的对于它的下一个儿子的其它子节点连接的最长链
    }
}

ll brt(int root)
{
    st = cnt+1, ans2 = 0, ans3 = 0;
    dfs(root, 0);
    for(int i=st; i<=cnt; i++)
    {
        ans = 0;
        tree_dp(r[i]);//以环上的每个点为根求树的直径
        ans2 = max(ans2, ans);
        //长度是cnt-(st-1)
        dp[i+cnt-st+1] = dp[i] = d[r[i]];
        s[i+cnt-st+1] = s[i+cnt-st]+s[i]-s[i-1];//s[i-1]就是s[0]的用途?
    }
    deque<int> q;
    for(int i=st; i<=2*cnt-st+1; i++)//i的终点好奇怪?
    //哦,虽然很绕,但它是对的,cnt+cnt-(st-1)第一个cnt是倍长前的部分的终点,再加上一个长度
    {
        while(q.size() && q.front()<=i-cnt+st-1)
        {
            q.pop_front();
        }
        if(q.size())
        {
            ans3 = max(ans3, dp[i]+dp[q.front()]+s[i]-s[q.front()]);
        }
        while(q.size() && dp[q.back()]-s[q.back()]<=dp[i]-s[i])
        {
            q.pop_back();
        }
        q.push_back(i);
    }
    return max(ans2, ans3);
}

int main()
{
    n = read();
    for(int i=1; i<=n; i++)
    {
        int y = read(), z = read();
        add(i, y, z); add(y, i, z);
    }
    for(int i=1; i<=n; i++)
    {
        if(!v2[i])
        {
            anss += brt(i);
        }
    }
    printf("%lld\n", anss);
    
    return 0;
}

 

标签:ch,const,int,ll,long,基环树,maxn,直径
来源: https://www.cnblogs.com/Catherine2006/p/16548965.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有