Codeforces Round 932 (Div. 2) ---- F. Andrey‘s Tree ---- 题解

F. Andrey's Tree:

题目描述:

思路解析:

我们假设删除任意一个结点后,我们会将整个树切分为k个联通块,那么可以明确的知道我们只需要连接(k-1)条边就可以将这k个联通块重新连为一棵树。

那么最小代价是啥呢? 图解分析

 第一种情况,有至少一个联通块即拥有小于删除点的数,又有大于删除的数,此时代价就是要增加的边数

第二种情况,没有上诉的联通块。

 我们可以发现我们还是可以将整个联通块连接为 (1,x-1) 和 (x+1,n)的两个联通块,花费为k-2,此时还需要2个花费,将整个联通块连接为(1,n)的联通块,总花费为删除结点后,联通块的个数。

经过此时分析,我们可以发现我们其实已知需要连多少条边,需要多少代价,这是固定的。花费只由是否有一个联通块中既有小于x的值和大于x的值决定。 因为初始是一棵树,那么假如有一条边为2-7,可以发现后面的边无论怎么样,对于删除3,4,6,来说,一定有个联通块含有(2和7)满足上诉要求,则此时可以通过前缀和来实现。

根据前两个图发现,只要两种连接情况 (x,x+1) (x,x-1)(y,y+2), 且x为联通块的最小值或者最大值,y=删除值-1,那么我们只要维护每个联通块的最小值和最大值即可,并且维护删除结点后,有哪些联通块即可。

代码实现:

import java.io.*;
import java.math.BigInteger;
import java.util.*;

import static java.util.Collections.*;

public class Main {
    static int inf = (int) 1e9;
    static int mod = 998244353;

    public static void main(String[] args) throws IOException {
        int t = f.nextInt();
        while (t > 0) {
            solve();
            t--;
        }

        w.flush();
        w.close();
        br.close();
    }

    static int[] maxIn;
    static int[] maxOut;
    static int[] minIn;
    static int[] minOut;
    static int[] p;
    static Vector<Integer>[] g;
    static int n;

    public static void solve() {
        n = f.nextInt();
        g = new Vector[n];
        for (int i = 0; i < n; i++) {
            g[i] = new Vector<>();
        }
        int[] d = new int[n];
        for (int i = 0; i < n - 1; i++) {
            int u = f.nextInt() - 1;
            int v = f.nextInt() - 1;
            g[u].add(v);
            g[v].add(u);
            if (u > v) {
                int tmp = u;
                u = v;
                v = tmp;
            }
            d[u + 1]++;
            d[v]--;
        }

        for (int i = 1; i < n; i++) {
            d[i] += d[i - 1];
        }
        d[0] = d[n - 1] = 1;
        for (int i = 0; i < n; i++) {
            d[i] = d[i] >= 1 ? 1 : 0;
        }
        maxIn = new int[n];
        minIn = new int[n];
        maxOut = new int[n];
        minOut = new int[n];
        p = new int[n];
        Arrays.fill(minOut, n);
        dfs1(0);
        dfs2(0);

        for (int x = 0; x < n; x++) {
            int res = g[x].size() - d[x];
            w.println(res + " " + (g[x].size() - 1));
            ArrayList<int[]> q = new ArrayList<>();
            for (int i = 0; i < g[x].size(); i++) {
                int y = g[x].get(i);
                if (y == p[x]){
                    q.add(new int[] {minOut[x], maxOut[x]});
                }else {
                    q.add(new int[]{minIn[y], maxIn[y]});
                }
            }
            int lst = -1;
            q.sort(new Comparator<int[]>() {
                @Override
                public int compare(int[] o1, int[] o2) {
                    return o1[0] - o2[0];
                }
            });
            for (int[] a : q) {
                if (a[0] >= x) break;
                if (lst != - 1) w.println(a[0] + 1 + " " + a[0]);
                lst = a[0];
            }
            lst = -1;
            q.sort(new Comparator<int[]>() {
                @Override
                public int compare(int[] o1, int[] o2) {
                    return o2[1] - o1[1];
                }
            });
            int c = 0;
            for (int[] a : q) {
                if (a[1] <= x) break;
                if (lst != - 1 && (c == 0 || a[0] > x)) w.println(a[1] + 2 + " " + (a[1] + 1));
                lst = a[0];
                c |= (a[0] < x ? 1 : 0);
            }
            if (c == 0 && x > 0 && x + 1 < n) w.println(x + " " + (x + 2));
            w.println();
        }

    }

    static void dfs1(int x) {
        minIn[x] = x;
        maxIn[x] = x;
        for (int i = 0; i < g[x].size(); i++) {
            int y = g[x].get(i);
            if (y == p[x]) continue;
            p[y] = x;
            dfs1(y);
            minIn[x] = Math.min(minIn[y], minIn[x]);
            maxIn[x] = Math.max(maxIn[y], maxIn[x]);
        }
    }

    static void dfs2(int x) {
        int[] mx = new int[2];
        int[] mn = new int[2];
        mn[0] = mn[1] = n;
        for (int i = 0; i < g[x].size(); i++) {
            int y = g[x].get(i);
            if (y == p[x]) continue;
            int a = minIn[y];
            int b = maxIn[y];
            for (int j = 0; j < 2; j++) {
                if (a < mn[j]){
                    int tmp = mn[j];
                    mn[j] = a;
                    a = tmp;
                }
                if (b > mx[j]){
                    int tmp = mx[j];
                    mx[j] = b;
                    b = tmp;
                }
            }
        }

        for (int i = 0; i < g[x].size(); i++) {
            int y = g[x].get(i);
            if (y == p[x]) continue;
            int a = mx[mx[0] == maxIn[y] ? 1 : 0];
            int b = mn[mn[0] == minIn[y] ? 1 : 0];
            maxOut[y] = Math.max(maxOut[x], Math.max(a, x));
            minOut[y] = Math.min(minOut[x], Math.min(b, x));
            dfs2(y);
        }
    }

    static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
    static Input f = new Input(System.in);
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    static class Input {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public Input(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public String nextLine() {
            String str = null;
            try {
                str = reader.readLine();
            } catch (IOException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
            return str;
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public Double nextDouble() {
            return Double.parseDouble(next());
        }

        public BigInteger nextBigInteger() {
            return new BigInteger(next());
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

uniapp 设置globalStyle navigationBarTitleText 不显示

设置全局的navigationBarTitleText但是没有显示 没效果: 原因: 这里实际上设置了navigationBarTitleText 为"" 所以不会使用全局的设置 解决方法就是直接将这一行代码删除

【YOLOv5改进系列(9)】高效涨点----使用CAM(上下文增强模块)替换掉yolov5中的SPPF模块

文章目录 &#x1f680;&#x1f680;&#x1f680;前言一、1️⃣ CAM模块详细介绍二、2️⃣CAM模块的三种融合模式三、3️⃣如何添加CAM模块3.1 &#x1f393; 添加CAM模块代码3.2 ✨添加yolov5s_CAM.yaml文件3.3 ⭐️修改yolo.py文相关文件 四、4️⃣实验结果4.1 &#x1f39…

RegionCLIP网络结构解析 Region-based Language-Image Pretraining

1、简单介绍 主要是关注目标检测方面的工作&#xff0c;现在纯CV已经前景黯淡&#xff0c;即使前段时间的YOLOv9发布也是关注一般。 现在大模型已成热点&#xff0c;而大模型要求的数据量和算力和算法复杂度&#xff0c;显然让很多人却步。但是具有大模型特点的多模态算法也算…

前端订阅后端推送WebSocket定时任务

0.需求 后端定时向前端看板推送数据&#xff0c;每10秒或者30秒推送一次。 1.前言知识 HTTP协议是一个应用层协议&#xff0c;它的特点是无状态、无连接和单向的。在HTTP协议中&#xff0c;客户端发起请求&#xff0c;服务器则对请求进行响应。这种请求-响应的模式意味着服务器…

江大白 | 万字长文,近3年Transformer在小目标检测领域,进展与突破系统梳理!

本文来源公众号“江大白”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;万字长文&#xff0c;近3年Transformer在小目标检测领域&#xff0c;进展与突破系统梳理&#xff01; 以下文章来源于微信公众号&#xff1a;AI视界引擎 …

基于wordcloud、matplotlib等对某东评论数据情感分析-Python数据分析项目

基于wordcloud、matplotlib等对某东评论数据情感分析 文章目录 基于wordcloud、matplotlib等对某东评论数据情感分析1 数据导入及预处理1.1 数据导入1.2 数据描述1.3 数据预处理 2 情感分析2.1 情感分析2.2 情感分直方图2.3 词云图2.4 关键词提取 3 积极评论与消极评论3.1 积极…

【协议】RPC

文章目录 概述与web service/web api/wcf区别简介区别和联系 grpc.Net Core示例 参考 概述 与web service/web api/wcf区别 简介 RPC&#xff08;Remote Procedure Call Protocol&#xff09;即远程过程调用协议&#xff0c;是分布式系统间通信的一种协议。通过网络从远程计…

三星加强Bixby智能:迈向生成式AI,抗衡谷歌Gemini

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

文件操作(详解)

该片博客有点长大家可以通过目录选择性阅读 这是个人主页 敲上瘾-CSDN博客 目录 1. 为什么使⽤⽂件&#xff1f; 2. 什么是⽂件&#xff1f; 2.1 程序⽂件 2.2 数据⽂件 2.3 ⽂件名 3. ⼆进制⽂件和⽂本⽂件&#xff1f; 4. ⽂件的打开和关闭 4.1 流和标准流 4.1.1 流…

29-控制流(下):iam-apiserver服务核心功能实现讲解

我们再来看下 iam-apiserver 中的核心功能实现。 这些关键代码设计分为 3 类&#xff0c;分别是应用框架相关的特性、编程规范相关的特性和其他特性。 应用框架相关的特性 应用框架相关的特性包括三个&#xff0c;分别是优雅关停、健康检查和插件化加载中间件。 优雅关停 …

二维码:技术、商业与未来

title: 二维码&#xff1a;技术、商业与未来 date: 2024/4/3 19:12:28 updated: 2024/4/3 19:12:28 tags: 二维码技术商业应用移动支付物联网AR/VR融合智能家居数字化社会 第一章&#xff1a;引言 1. 二维码在数字化时代的重要性和普及程度 在数字化时代&#xff0c;二维码作…

程序员的升级打怪之路

#程序人生 写在前面 转眼间&#xff0c;我已经进入程序员的大门已经近4个春秋了&#xff08;算上实习的话&#xff0c;那就是快5年了…&#x1f436;.&#x1f436;.&#x1f436;不能再展开了&#xff0c;再不就暴露年龄了&#x1f605;&#xff09;。 这段时间&#xff0c…

element-ui card 组件源码分享

今日简单分享 card 组件源码&#xff0c;主要从以下两个方面&#xff1a; 一、card 组件页面结构 二、card 组件属性 2.1 header 属性&#xff0c;设置 header&#xff0c;也可以通过 slot#header 传入 DOM&#xff0c;类型 string&#xff0c;无默认值。 组件使用部分&#…

[做cpu] 第二次仿真实验

实现ori指令后&#xff0c;还得解决流水中数据相关的事&#xff0c;MIPS中只需要解决RAW&#xff08;在写操作后读&#xff09;&#xff0c;利用数据前推解决 相隔两条指令&#xff0c; 通过标志位判断直接把回写的内容作为读入译码的数据。 仿真出错原因&#xff1a;在顶层模…

spring总结-基于XML管理bean超详细

spring ioc总结-基于XML管理bean 前言实验一 [重要]创建bean1、目标和思路①目标②思路 2、创建Maven Module3、创建组件类4、创建spring配置文件7、无参构造器8、用IOC容器创建对象和自己建区别 实验二 [重要]获取bean1、方式一&#xff1a;根据id获取2、方式二&#xff1a;根…

20.安全性测试与评估

每年都会涉及&#xff1b;可能会考大题&#xff1b;多记&#xff01;&#xff01;&#xff01; 典型考点&#xff1a;sql注入、xss&#xff1b; 从2个方面记&#xff1a; 1、测试对象的功能、性能&#xff1b; 2、相关设备的工作原理&#xff1b; 如防火墙&#xff0c;要了解防…

redis---主从复制

主从复制是指将一台redis服务器的数据复制到其他redis服务器&#xff0c;也叫主节点和从节点。 一个主节点可以有多个从节点。而每个从节点只能有一个主节点。数据的复制是单向的&#xff0c;只能由主节点到从节点。一般来说&#xff0c;主节点负责写操作&#xff0c;从节点负…

公众号搜索被降权后多久能恢复?

公众号搜索被降权后的恢复时间是一个复杂的问题&#xff0c;它涉及到多种因素的综合考量。首先&#xff0c;违规的严重程度是一个重要的因素。如果违规行为较为轻微&#xff0c;可能只需要较短的时间就能恢复搜索权重;而如果违规行为较为严重&#xff0c;可能需要更长的时间&am…

vue实现导出列表为xlsx文件

1.安装依赖 npm install --save xlsx file-saver 2.引入依赖 import FileSaver from file-saver; import * as XLSX from xlsx; 3.代码实现 <el-button type"primary" click"exportData">导出数据</el-button><el-tableid"table_ex…

与 ChatGPT 对话

原文&#xff1a;Conversing With ChatGPT 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 ChatGPT 人工智能 尽管人工智能带来了许多好处和进步&#xff0c;但仍有一些话题引发担忧并引发道德、社会和存在问题。以下是与人工智能相关的一些最可怕的话题&#xff1a…