[NOI 2015复习][BZOJ 1509][NOI 2003]逃学的小孩(树的直径)

2023-11-17

题目链接

http://www.lydsy.com/JudgeOnline/problem.php?id=1509

题目大意

要从一棵树中找出三个点 X,Y,Z ,使得 min(dis[A][C],dis[B][C])+dis[A][B] 最大,求这个最大值

思路

可以发现,min里头的两个东西具体取哪个并不重要,或者说点C距离A更近还是距离B更近并不重要。下面给出一个结论: min(dis[A][C],dis[B][C])+dis[A][B] 取最大值时,路径AB是整个树的直径(最长链),通过BFS找出树的直径后,直接枚举点C即可得到最大答案。

不过复习此题主要还是为了复习树的直径的求法。可以通过两次BFS求出树的直径AB(树上最长链AB):
第一次BFS:任意选择一个起点,搜出距离这个点最远的点A,也就是最长链的一个端点。
第二次BFS:选择A作为起点,搜出距离这个点最远的点B,也就是最长链的另一个端点。

第二次BFS的正确性是显然的,因为如果我们已经知道了最长链的一个端点,就能很容易地通过求最长路来求出最长链的另外一个端点。

下面证明第一次BFS的正确性。
Case 1.第一次BFS选择的起点在最长链上。此时假如得到的最远点A不是最长链端点,那么显然就会存在A‘,A’到起点距离比A到起点距离更远,然而BFS找出的是距离起点最远的点,与之前矛盾,证毕。

Case 2.第一次BFS选择的起点不在最长链上,且此时起点到A的路径和最长链相交,设交点为x,则x到A的路径必然是最长链的后半段。假如不是的话,就能存在A’(A’就是最长链的端点),使得x到A‘距离比x到A距离更远,最长链的后半段也因此是xA’而不是xA,同样地,A‘比A距离起点更远,这是显然的。但是由于BFS找出的是距离起点最远的点,与之前矛盾,故不存在这样的A‘,xA就是最长链的后半段,证毕。

Case 2.第一次BFS选择的起点不在最长链上,且此时起点到A的路径和最长链不相交
显然最长链的长度应该比起点到A长度更长,若相等的话,起点到A的链就同样是最长链了。
dd

考虑上图。由于是树,所以起点到A的链和最长链端点之间必然存在一条如图所示的红色路径。

显然X-A长度比X-5长度短,因为X-5是最长链。因此2-A长度比2-5长度短。1-A长度(2-A长度-1)比1-5长度短(2-5长度+1),也就是说A比5距离起点更近。而BFS找出的是离起点最远的点,与之前矛盾,故不存在Case 3。证毕。

代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MAXN 210000

using namespace std;

typedef long long int LL;

struct edge
{
    int u,v,w,next;
}edges[MAXN*2];

int head[MAXN],nCount=0;

void AddEdge(int U,int V,int W)
{
    edges[++nCount].u=U;
    edges[nCount].v=V;
    edges[nCount].w=W;
    edges[nCount].next=head[U];
    head[U]=nCount;
}

int n,m;
bool vis[MAXN];
int q[MAXN];

int BFS(int S,LL dist[]) //求出每个点到S的距离,保存在dist[]里,并返回距离S最远的点
{
    memset(vis,false,sizeof(vis));
    int h=0,t=1;
    q[h]=S;
    dist[S]=0;
    vis[S]=true;
    int farthest=0; //最远点
    while(h<t)
    {
        int u=q[h++];
        for(int p=head[u];p!=-1;p=edges[p].next)
        {
            int v=edges[p].v;
            if(vis[v]) continue;
            vis[v]=true;
            dist[v]=dist[u]+edges[p].w;
            q[t++]=v;
            vis[v]=true;
            if(dist[v]>dist[farthest]) farthest=v;
        }
    }
    return farthest;
}

LL dista[MAXN],distb[MAXN];

int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        AddEdge(u,v,w);
        AddEdge(v,u,w);
    }
    int a=BFS(1,dista);
    int b=BFS(a,dista);
    BFS(b,distb);
    LL ans=0;
    for(int i=1;i<=n;i++)
        ans=max(ans,min(dista[i],distb[i]));
    printf("%lld\n",ans+dista[b]);
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[NOI 2015复习][BZOJ 1509][NOI 2003]逃学的小孩(树的直径) 的相关文章

  • Connections between cities 【HDU - 2874】【在线LCA算法】

    题目链接 昨天刚学了在线LCA 今天就来硬刚这道题还是花了一整天的时间 不过对于LCA却有了更多的理解 这道题在讲述不同根的做法上尤其是很好的 题目告诉我们有N个节点和M条边 以及C次询问 每次查询的是 L R 这两个节点间的距离 还是算得
  • AcWing 1055. 股票买卖 II

    输入样例1 6 7 1 5 3 6 4 输出样例1 7 输入样例2 5 1 2 3 4 5 输出样例2 4 输入样例3 5 7 6 4 3 1 输出样例3 0 样例解释 样例1 在第 2 天 股票价格 1 的时候买入 在第 3 天 股票价格
  • [NOIP 2014复习]第二章:搜索

    一 深度优先搜索 DFS 1 Wikioi 1066引水入城 题目描述 Description 在一个遥远的国度 一侧是风景秀美的湖泊 另一侧则是漫无边际的沙漠 该国的行政 区划十分特殊 刚好构成一个N行M列的矩形 如上图所示 其中每个格子
  • 图论进阶指南-银河(差分约束/DAG/tarjan)

    测评地址 题目大意 第一行给出两个整数N和M 之后M行 每行三个整数T A B 表示一对恒星 A B 之间的亮度关系 恒星的编号从1开始 如果T 1 说明A和B亮度相等 如果T 2 说明A的亮度小于B的亮度 如果T 3 说明A的亮度不小于B
  • 关于暴力&瞎搞骗分的一些实例

    骗分的实质 不会做的题用最少的时间写代码得到最多的分数 下面是几个乱搞骗分的实例 抛砖引玉让大家感受下骗分的强大 1 NOI 2008 志愿者招募 http codevs cn problem 1803 根据题目范围可以想到直接搜索骗分 期
  • UVA-1601 万圣节后的早晨 题解答案代码 算法竞赛入门经典第二版

    GitHub jzplp aoapc UVA Answer 算法竞赛入门经典 例题和习题答案 刘汝佳 第二版 以三个点的当前位置作为状态 广度优先遍历 找到终点即为最短次数 注意 一次可以移动多个点 但是每个点只能移动一步 在同一次中 B可
  • lambda

    外部变量访问方式说明符 不捕获任何变量 以引用方式捕获所有变量 用值的方式捕获所有变量 可能被编译器优化为const foo 以引用捕获foo 但其余变量都靠值捕获 foo 以值捕获foo 但其余变量都靠引用捕获 bar 以值方式捕获bar
  • 二分图最大完美匹配

    嗯 想不通 就是二分之后的点 寻找左边的点和右边的点的保证两条边的顶点不相同的最大边数 匈牙利算法 O mn 左边寻找和右边相邻的边 如果右边还没有和左边进行连线 那么匹配成功 如果右边已经进行连线 那么考虑左边是否能更改连线 换一个右边
  • 数据结构 图的应用

    文章目录 生成树 定义 性质 带权图的最小生成树 最小生成树的生成规则 最小生成树 Kruskal算法 步骤 最小生成树 Prim算法 步骤 最短路径 非负权值的单源最短路径 Dijkstra算法 目的 算法 存储空间 算法步骤 算法实现
  • P1218 [USACO1.5]特殊的质数肋骨 Superprime Rib【普及】

    USACO1 5 特殊的质数肋骨 Superprime Rib 题目描述 农民约翰的母牛总是产生最好的肋骨 你能通过农民约翰和美国农业部标记在每根肋骨上的数字认出它们 农民约翰确定他卖给买方的是真正的质数肋骨 是因为从右边开始切下肋骨 每次
  • 图论17(Leetcode864.获取所有钥匙的最短路径)

    用二进制表示获得的钥匙 假设n 钥匙个数 000000000代表没有钥匙 0000000001代表有idx为1的钥匙 0000000011代表有idx 1 2的钥匙 这方法巧妙又复杂 代码 class Solution static int
  • 2021级新生个人训练赛第38场

    问题 A chicken 题目描述 小 x 非常喜欢小鸡翅 他得知 NSC 超市为了吸引顾客 举行了如下的活动 一旦有顾客在其他超市找到更便宜的小鸡翅 NSC 超市将免费送给顾客 1000g 小鸡翅 小 x 为了尽可能的省钱 走遍了各大超市
  • PCL点云处理之批量读写点云、随机赋予颜色 并保存

    include
  • 【DFS和BFS习题集+分类总结】(更新至2023.1.1)(17788字)

    目录 第一题 八皇后 dfs 路径输出 前驱版 第一题的补充练习 N皇后 dfs 打表 第二题 自然数的拆分 第三题 图的遍历 BFS和DFS 第四题 fire net dfs 第五题 nightmare 可以走回头路的DFS 第六题 滑雪
  • 数据结构练习题——图(含应用题)

    1 选择题 1 在一个图中 所有顶点的度数之和等于图的边数的 倍 A 1 2 B 1 C 2 D 4 答案 C 2 在一个有向图中 所有顶点的入度之和等于所有顶点的出度之和的 倍 A 1 2 B 1 C 2 D 4 答案 B 解释 有向图所
  • BZOJ3425 Poi2013 Polarization

    最小值一定是n 1 每条边贡献一个答案 显然 首先我们要证明这道题的一个性质 最优解一定具有如下形式 以树的某一个重心 可以是任意一个 为根 根的每一个子树里的所有边要么都指向根 要么都指向叶子 引理 首先对于一棵树 我们把所有边的朝向反转
  • How far away ? 【HDU - 2586】【DFS+链式前向星优化】

    题目链接 其实这道题可以不用链式前向星优化换做vector lt gt 也是可以跑的 只是会许会慢些而已 来换个中文题意好读些 勇气小镇是一个有着n个房屋的小镇 为什么把它叫做勇气小镇呢 这个故事就要从勇气小镇成立的那天说起了 修建小镇的时
  • 图论--最近公共祖先LCA

    最近公共祖先LCA LCA Least Common Ancestors 即最近公共祖先 是指这样一个问题 在有根树中 找出某两个结点u和v最近的公共祖先 另一种说法 离树根最远的公共祖先 最近公共祖先是相对于两个节点来说的 一般来说 最近
  • 有向图的拓扑排序

    给定一个 nn 个点 mm 条边的有向图 点的编号是 11 到 nn 图中可能存在重边和自环 请输出任意一个该有向图的拓扑序列 如果拓扑序列不存在 则输出 1 1 若一个由图中所有点构成的序列 AA 满足 对于图中的每条边 x y x y
  • D (1173) : A DS二叉树_合并二叉树

    文章目录 一 题目描述 二 输入与输出 1 输入 2 输出 三 参考代码 一 题目描述 给定两个二叉树 输出这两个二叉树合并后形成的二叉树 依次输出前序遍历 中序遍历 后序遍历 二 输入与输出 1 输入 第一行输入t 表示有t个测试样例 第

随机推荐