P4381 [IOI2008] Island (求基环树直径)

news2024/11/17 7:51:32

也许更好的阅读体验

D e s c r i p t i o n \mathcal{Description} Description
给一个基环树森林,求每棵树的直径的和,基环树的直径定义为,从一个点出发只能走到没走过的点(即一个环不能把所有边都选),所经过的路径边权和最大

S o l u t i o n \mathcal{Solution} Solution
这题不是很难,只是略微麻烦,代码也好打,一遍就过了
对于每棵基环树独立搞

先找到这棵树的环,这个过程分为两步,第一步找到换上的一条边,可以利用类似网络流的存边方法给走过的边记录是否走过,给走过的点标记是否走过,当走一条没走过的边可以走到走过的点,说明这条边是环上的边,第二步从环上的点出发如果走一条没走过的边发现可以走到环上的点,说明这个点就在环上

找到环后,基环树会是这样的:

在这里插入图片描述
以下称环上的点的子树指的就是,以环上一点作为根节点,屏蔽要经过环上其它点的点所得子树(就是图中画的那样)
考虑直径的形式,第一种是没有经过环上的点,也就是在图中某个环上节点的子树中,第二种是经过环上的点
对于第一种,我们对环上每个点的子树求一边树的直径就可以了
对于第二种情况,这时直径会是,两个环上的点的子树中最长的链的长度相加再加上这两点在环上的最大距离,我们将每个环上的点的子树最长链的长度看作点权,就变成求环上两点的最大距离加上两点点权的和最大
这个过程并不难整,设环上所有边权加起来为 s u m sum sum,用 d i d_i di表示该点逆时针走一步的边权,再设定一个起始点做一个前缀和记为 s i s_i si,则两点逆时针路径即为 s i − s j s_i-s_j sisj,顺时针路径即为 s u m − ( s i − s j ) sum-(s_i-s_j) sum(sisj),记 m x i mx_i mxi表示该点点权(子树中最长链长度),则就是要求 m a x { d i + d j + d i s ( i , j ) } max\{d_i+d_j+dis(i,j)\} max{di+dj+dis(i,j)},其中由于 d i s ( i , j ) dis(i,j) dis(i,j)可能是顺时针的也可能是逆时针的,干脆对顺时针和逆时针分别求一次,这样 d i s ( i , j ) = s i − s j dis(i,j)=s_i-s_j dis(i,j)=sisj,就是要求 m a x { d i + d j + s i − s j } max\{d_i+d_j+s_i-s_j\} max{di+dj+sisj},这个只要记下前面最大的 d j − s j d_j-s_j djsj即可

C o d e \mathcal{Code} Code

#include <cstdio>
#include <algorithm>
#include <deque>
#define ll long long
using namespace std;
const int maxn = 1e6 + 10;
const int maxm = 2e6 + 10;
int n, cnt = 1, now, tot, tim;
int head[maxn], nxt[maxm], to[maxm], w[maxm], q[maxn];
int vis[maxn], used[maxm];
ll ans, sum, mxl;
ll mx1[maxn], mx2[maxn], d[maxn];
void add (int u, int v, int val) { nxt[++cnt] = head[u], head[u] = cnt, to[cnt] = v, w[cnt] = val; }
void dfs (int u)//找环上的一条边放在now里
{
    vis[u] = tim;
    for (int e = head[u]; e; e = nxt[e])
        if (used[e] != tim) {
            used[e] = used[e ^ 1] = tim;
            if (vis[to[e]] != tim)    dfs(to[e]);
            else    now = e;
        }
}
bool dfs2 (int u)//将环上的点放进q 需要从环上的点出发
{
    vis[u] = tim;
    bool flag = false;
    for (int e = head[u]; e; e = nxt[e])
        if (used[e] != tim) {
            used[e] = used[e ^ 1] = tim;
            if (vis[to[e]] == tim)  q[++tot] = u, d[tot] = w[e], flag = true;
            else if (dfs2(to[e]))   q[++tot] = u, d[tot] = w[e], flag = true;
        }
    return flag;
}
void solve (int u)//求出该点为根的子树最长链和直径
{
    vis[u] = tim;
    for (int e = head[u]; e; e = nxt[e])
        if (vis[to[e]] != tim) {
            solve(to[e]);
            ll len = mx1[to[e]] + w[e];
            if (len > mx2[u])   mx2[u] = len;
            if (mx2[u] > mx1[u])    swap(mx1[u], mx2[u]);
        }
    mxl = max(mxl, mx1[u] + mx2[u]);
}
void dp ()
{
    ++tim;
    sum = mxl = 0;
    for (int i = 1; i <= tot; ++i)  vis[q[i]] = tim, sum += d[i];
    for (int i = 1; i <= tot; ++i)  solve(q[i]);
    for (int i = 2; i <= tot; ++i)  d[i] += d[i - 1];
    int p = 1;
    for (int i = 2; i <= tot; ++i) {
        mxl = max(mxl, mx1[q[i]] + mx1[q[p]] + d[i] - d[p]);
        if (mx1[q[i]] - d[i] > mx1[q[p]] - d[p])  p = i;
    }
    p = 1;
    for (int i = 2; i <= tot; ++i) {
        mxl = max(mxl, mx1[q[i]] + mx1[q[p]] + sum - d[i] + d[p]);
        if (mx1[q[i]] + d[i] > mx1[q[p]] + d[p])  p = i;
    }
    ans += mxl;
}
int main ()
{
    scanf("%d", &n);
    for (int i = 1, v, val; i <= n; ++i) {
        scanf("%d%d", &v, &val);
        add(i, v, val), add(v, i, val);
    }
    for (int i = 1; i <= n; ++i)
        if (!vis[i]) {
            ++tim;
            dfs(i);
            ++tim, tot = 0;
            dfs2(to[now]);
            dp();
        }
    printf("%lld\n", ans);
    return 0;
}

如有哪里讲得不是很明白或是有错误,欢迎指正
如您喜欢的话不妨点个赞收藏一下吧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/852998.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

史上最细,自动化测试-logging日志采集详细实战(二)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、测试场景 给登…

固态硬盘数据恢复方法有哪些?三种恢复方法助您解忧

近年来固态硬盘比较流行&#xff0c;因为工作的需要我也在使用固态硬盘&#xff0c;它真的给我带来了很多的方便。但是最近&#xff0c;我固态硬盘里的文件有些不知道怎么就丢失了&#xff0c;这给我带来了很大的困扰。有什么方法可以找回来吗&#xff1f; 固态硬盘&#xff08…

Netty客户端同步获取结果

上次服务间通信是异步的&#xff0c;现在想实现客户端同步拿到服务端响应结果。实现如下&#xff1a; 在NettyClientHandler类中增加一个结果缓存器 Map<Long,Protocol<ResponseMsg>> resultMap new ConcurrentHashMap<>();修改方法 Override protected vo…

【文献阅读笔记】深度异常检测模型

文章目录 导读相关关键词及其英文描述记录深度异常检测模型Supervised deep anomaly detection 有监督深度异常检测Semi-Supervised deep anomaly detection 半监督深度异常检测Hybrid deep anomaly detection 混合深度异常检测One-class neural network for anomaly detection…

VR全景的盈利模式你知道吗?VR全景能用在哪些领域?

引言&#xff1a; 随着科技的迅猛发展&#xff0c;虚拟现实技术已经逐渐走进我们的生活。这项令人惊叹的技术让我们能够穿越时间与空间的限制&#xff0c;重新定义人们与世界互动的方式。 一&#xff0e;什么是VR全景&#xff1f; VR全景&#xff0c;是一种通过虚拟现实技术&…

万应低代码受邀参加上海电信“大干一场 科创沙龙”活动

7月28日&#xff0c;由上海市宝山区大场镇政府指导、中国电信上海北区局主办的“大干一场 科创沙龙”系列第九期沙龙活动顺利举办。大场镇“数字化转型”领导小组办公室&#xff08;以下简称“数字办”&#xff09;邀请了来自镇域内外的数十家科创服务企业。万应低代码作为天翼…

D5渲染器有多强大?给你10个选择它的理由

使用此分步指南&#xff0c;可以轻松快速地使用 D5 Render 创建专业视觉效果。使用 D5 Render 创建的视觉效果能够快速有效地传达信息。例如&#xff0c;简单的图形或图表可用于比较不同的数据集或显示变量之间的关系。使用 D5 Render&#xff0c;您可以创建既美观又信息丰富的…

公检系统创新:利用校对软件优化法律文书流程

公检系统可以通过利用校对软件来优化法律文书的流程&#xff0c;从而提高效率和准确性。以下是在创新方面利用校对软件的一些方法&#xff1a; 1.自动校对和修正&#xff1a;校对软件可以与公检系统集成&#xff0c;自动检测文书中的拼写、语法和标点符号错误&#xff0c;并提供…

msvcp120.dll丢失的4种解决方法,教你修复msvcp120.dll文件

当你在使用计算机时&#xff0c;经常会遇到各种各样的错误&#xff0c;最近遇到的应该就是dll文件缺失的错误吧&#xff0c;今天主要来跟大家讲解一下msvcp120.dll这个文件&#xff0c;教大家msvcp120.dll丢失的4种解决方法&#xff0c;好了&#xff0c;废话不多说&#xff0c;…

北京多铁克FPGA笔试题目

1、使用D触发器来实现二分频 2、序列检测器&#xff0c;检测101&#xff0c;输出1&#xff0c;其余情况输出0 module Detect_101(input clk,input rst_n,input data, //输入的序列output reg flag_101 //检测到101序列的输出标志 );parameter S0 2d0;S1 2d1;S2 2d2;S4 …

从金蝶云星空到金蝶云星空通过接口配置打通数据

从金蝶云星空到金蝶云星空通过接口配置打通数据 对接系统金蝶云星空 金蝶K/3Cloud结合当今先进管理理论和数十万家国内客户最佳应用实践&#xff0c;面向事业部制、多地点、多工厂等运营协同与管控型企业及集团公司&#xff0c;提供一个通用的ERP服务平台。K/3Cloud支持的协同应…

【LeetCode】数据结构题解(12)[用栈实现队列]

用栈实现队列 &#x1f609; 1.题目来源&#x1f440;2.题目描述&#x1f914;3.解题思路&#x1f973;4.代码展示 所属专栏&#xff1a;玩转数据结构题型❤️ &#x1f680; >博主首页&#xff1a;初阳785❤️ &#x1f680; >代码托管&#xff1a;chuyang785❤️ &…

flask使用cookie (设置cookie与查看cookie内容)

1.flask包cookie的使用 设置cookie app.route(/set_cookie) def set_cookie():resp make_response(Setting cookie)resp.set_cookie(username, John)return resp查看cookie: app.route(/get_cookie) def get_cookie():username request.cookies.get(username)return Welco…

gazebo 导入从blender导出的dae等文件

背景&#xff1a; gazebo 模型库里的模型在我需要完成的任务中不够用&#xff0c;还是得从 solidworks、3DMax, blender这种建模软件里面在手动画一些&#xff0c;或者去他们的库里面在挖一挖。 目录 1 blender 1-1 blender 相关links 1-2 install 2 gazebo导入模型 2-1 g…

使用imu_tools对imu_raw进行滤波处理

文章目录 1 前言2 安装3 查找自己的IMU话题4 imu_tools滤波 1 前言 imu_filter_madgwick&#xff1a;一种滤波器&#xff0c;可将来自常规IMU设备的角速度&#xff0c;加速度和磁力计读数&#xff08;可选&#xff09;融合到一个方向中。基于工作&#xff1a;http://www.x-io.…

电力系统电流三段式保护MATLAB仿真模型

整体模型如下&#xff1a; Matlab/Simulink搭建的电力系统电流保护模型采用辐射型单电源供电的运行方式 Ⅰ段保护的搭建 Ⅰ段保护为瞬时速断保护&#xff0c;根据Ⅰ段整定原则确定整定值。线路发生短路故障时&#xff0c;短路电流急剧增大&#xff1b;超过设置的整定值时&…

lokibot样本分析

火绒剑行为监控 行为监控 1.主程序在temp文件夹下释放frhdgr.exe 2.并创建进程 参数为 C:\Users\xxx\AppData\Local\Temp\frhdgr.exe C:\Users\xxx \AppData\Local\Temp\vxogkynyop 3.主进程退出 4.frhdgr.exe自我删除 并释放C:\Users\xxx\AppData\Roaming\F503CB\B28854…

【ARM Cache 系列文章 8 -- ARM DynamIQ 技术介绍

文章目录 DynamIQ 技术背景DynamIQ技术详解DynamIQ 与 big.LITTLEDynamIQ cluster 分类硬件支持 DynamIQ为什么适合人工智能&#xff1f; DynamIQ 技术背景 2017年3月21日下午&#xff0c;ARM在北京金隅喜来登酒店召开发布会&#xff0c;正式发布了全新的有针对人工智能及机器…

推动多云管理平台发展的因素简单分析

随着云计算的快速发展&#xff0c;上云企业的不断增加&#xff0c;使用多云管理平台企业也在快速增加&#xff0c;多云管理平台发展越来越迅速。但还有不少人不明白为什么多云管理平台发展会这么快&#xff0c;推动多云管理平台发展的因素有哪些&#xff1f;今天我们大家就来简…