首页 > 其他分享 >T2【noip赛前20天冲刺集训 day4】正在打模拟赛

T2【noip赛前20天冲刺集训 day4】正在打模拟赛

时间:2023-10-12 19:34:19浏览次数:33  
标签:连通 20 noip val int day4 定义 节点 边权

@@ 【noip赛前20天冲刺集训 day4】正在打模拟赛 @@

题目描述

给定一棵包含 n 个点的树,每条边都有权值,同时给定一个整数 k。定义一个树上连通块的权值为其中边权之和。你需要求解满足以下条件的树上连通块的权值最大值:这个连通块至多包含一个度数大于 k 的点。

注意,这里的度数指的是连通块内节点的度数,而不是原始树上的度数。

输入格式

第一行包含两个非负整数 n 和 k。

接下来 n - 1 行,每行包含三个非负正整数 u, v, w,表示一条边,其中 u 和 v 是连接的两个节点,w 是边的权值。

输出格式

输出一个非负整数,表示满足条件的连通块的最大权值。

样例

输入样例 1

8 2
1 4 1
2 4 2
3 4 4
4 5 8
5 6 16
5 7 32
5 8 64

输出样例 1

124

样例解释

在这个样例中,可以选择由节点 3, 4, 5, 6, 7, 8 组成的连通块。

数据范围

本题包含多个子任务,其数据范围如下:

子任务 1:n ≤ 2 × 10^3,无特殊性质,分值 18。
子任务 2:n ≤ 2 × 10^5,k ≤ min{10, n - 1},分值 21。
子任务 3:n ≤ 2 × 10^5,对于 ∀i∈[2,n],存在边 (i-1, i),分值 13。
子任务 4:n ≤ 2 × 10^5,对于 ∀i∈[2,n],存在边 (1, i),分值 12。
子任务 5:n ≤ 2 × 10^5,无特殊性质,分值 36。

对于所有数据,保证 1 ≤ n ≤ 2 × 10^5,0 ≤ k < n,0 ≤ w ≤ 10^9。

解题思路

这个问题要求我们在一个树形结构中找到一个特定的连通块,其中至多只有一个节点的度数可以超过k,而且我们需要最大化这个连通块中所有边的权重和。这是一个优化问题,涉及到在满足特定条件的情况下最大化一个参数(本例中是边的权重和)。为了解决这个问题,我们将使用换根动态规划结合贪心策略。

换根动态规划

  1. 首先,我们对树进行一次深度优先搜索(DFS),这个搜索帮助我们计算两件事:

  2. 对于每个节点 u,我们都找出了一个包含 u 的连通块,这个连通块中的每个节点的度数都不超过 k,同时 u 的度数小于 k,同时我们尽可能地最大化了这个连通块中边的权重和。这是通过 dfs0 函数完成的。

  3. 接下来,我们需要考虑的是:如果我们移除了 u 及其子树,我们能否在包含 u 的父节点的子树中找到一个新的连通块,同时满足度数限制并且也尽可能地最大化边的权重和。这就是为什么我们需要进行第二次DFS,并且在这次DFS中,我们会“换根”。这是通过 dfs1 函数完成的。

贪心策略

  • 在我们的DFS过程中,我们实际上在每个步骤中都在应用贪心策略。我们的目标是最大化连通块的边权和,因此我们总是倾向于选择权重最大的边。在 dfs0 中,我们将每个节点的所有子树的权值存储在一个数组中,并对其进行排序,这样就可以很容易地选择权值最大的边。

  • dfs1 中,我们对父节点应用了类似的策略,但这次是在考虑了“换根”之后。我们试图构建一个新的连通块,它包含了当前节点的父节点,并且在满足度数限制的同时,也尽可能地最大化了边的权重和。

  • 通过这种方式,换根动态规划允许我们考虑树中的所有可能的连通块,而贪心策略则确保我们在满足度数限制的同时最大化了边的权重和。结合这两种策略,我们能够有效地遍历整棵树,找到满足题目要求的权值最大的树上连通块。

#include <bits/stdc++.h>
using namespace std;

#define int long long  // 使用宏定义将int定义为长整型,便于处理大数
#define mp make_pair   // 宏定义,简化make_pair的书写
#define pb emplace_back // 宏定义,简化emplace_back的书写,用于向容器中添加元素
#define rep(i, s, e) for (int i = s; i <= e; ++i)  // 宏定义,简化for循环(从s到e)
#define drep(i, s, e) for (int i = s; i >= e; --i)  // 宏定义,简化倒序for循环(从s到e)
#define file(a) freopen(#a ".in", "r", stdin), freopen(#a ".out", "w", stdout) // 宏定义,用于重定向输入输出到文件
#define pv(a) cout << #a << " = " << a << endl  // 宏定义,用于打印变量名和变量值
#define pa(a, l, r) cout << #a " : "; rep(_, l, r) cout << a[_] << ' '; cout << endl  // 宏定义,用于打印数组或容器的一部分

using pii = pair<int, int>;  // 定义pii为int类型的pair,用于存储两个整数

const int N = 2e5 + 10;  // 定义常量N,作为数组的最大大小

int read() {
    int x = 0, f = 1;
    char c = getchar();  // 定义结果变量x和符号变量f,使用getchar()读取一个字符
    for (; c < '0' || c > '9'; c = getchar())
        if (c == '-')
            f = -1;  // 跳过非数字字符,检查负号
    for (; c >= '0' && c <= '9'; c = getchar())
        x = x * 10 + c - 48;  // 计算数字的值
    return x * f;  // 如果检测到负号,则返回负值
}

int n, k, f[N], g[N], rk[N], ans;  // 定义输入的n, k,数组f, g, rk以及结果变量ans
vector<pii> e[N];  // 定义数组e,每个元素是一个vector,存储pair<int, int>

// 函数dfs0:第一次深度优先搜索,计算每个节点作为根时的最大边权和
void dfs0(int u, int fa) {
    vector<int> val;  // 定义一个vector存储值
    for (auto it : e[u]) {  // 遍历与节点u相连的所有节点
        int v = it.first, w = it.second;  // 获取相邻节点的编号和边权
        if (v != fa) {  // 如果邻接节点不是父节点
            dfs0(v, u);  // 递归进行深度优先搜索
            val.emplace_back(f[v]);  // 将该节点的最大边权和加入到val中
        } else
            f[u] = w;  // 否则,当前节点的最大边权和就是与父节点相连的边权
    }
    sort(val.begin(), val.end());  // 将val中的值进行排序
    reverse(val.begin(), val.end());  // 将val中的值进行反转,使之按降序排列
    int cnt = 0;  // 定义计数变量cnt
    for (int x : val) {  // 遍历val中的每个值
        if (cnt == k)
            break;  // 如果cnt达到k,则终止循环
        f[u] += x, ++cnt;  // 否则,将x加到f[u]上,并增加cnt
    }
}

// 函数dfs1:第二次深度优先搜索,换根并更新最终答案
void dfs1(int u, int fa) {
    int res = g[u];  // 定义变量res为g[u],表示不包括u的其他部分的最大边权和
    for (auto it : e[u]) {  // 遍历与节点u相连的所有节点
        int v = it.first, w = it.second;  // 获取相邻节点的编号和边权
        if (v != fa)
            res += f[v];  // 如果邻接节点不是父节点,将f[v]加到res上
    }
    ans = max(ans, res);  // 更新最终答案
    vector<pii> val;  // 定义一个vector存储pair
    val.pb(mp(g[u], 0));  // 将g[u]和0作为一个pair加入到val中
    for (auto it : e[u]) {  // 遍历与节点u相连的所有节点
        int v = it.first, w = it.second;  // 获取相邻节点的编号和边权
        if (v != fa)
            val.pb(mp(f[v], v));  // 如果邻接节点不是父节点,将f[v]和v作为一个pair加入到val中
    }
    sort(val.begin(), val.end());  // 将val中的值进行排序
    reverse(val.begin(), val.end());  // 将val中的值进行反转,使之按降序排列
    int d = val.size(), s = 0;  // 定义变量d为val的大小,s为0
    rep(i, 0, d - 1) rk[val[i].second] = i;  // 记录每个节点在val中的位置
    rep(i, 0, min(d, k) - 1) s += val[i].first;  // 计算s为val中前k个值的和
    for (auto it : e[u]) {  // 遍历与节点u相连的所有节点
        int v = it.first, w = it.second;  // 获取相邻节点的编号和边权
        if (v == fa)
            continue;  // 如果邻接节点是父节点,则
    }
}

标签:连通,20,noip,val,int,day4,定义,节点,边权
From: https://www.cnblogs.com/Serein-KarBlog/p/17760378.html

相关文章

  • 2023/10/12 博沃创新 面试
    2023年应届生6个月试用期被裁第一次社招16号辞职前4天  心里空落落  对自己很失望面试计7-8min心里大受打击好菜啊1.关于BMS的实现细节上问题对于OCV值怎么校正的?答的太差了 在初始化3s内进行校正  DOD2OCV来实现  又问极化存在很长时间怎么办?没回答上......
  • 2020,2021 年 CF 简单题精选 做题记录
    2023.10.12开坑,打了几场div.2之后一直觉得这方面水平差太多,今天刚好在洛谷看到这个题单就准备开始做了,里面从黄到黑都有,我会尽量都做,并在这里记录。总共49题,我可能平时有时间就做一两题,估计是个长期坑了((。题单链接[Y]表示独立完成,[N]表示看题解之后完成。......
  • 2023/10/12 学习笔记2
    一、信号与数制转换1.1 信号相关概念1.1.1 信息:不同领域对信息有不同的定义,一般认为信息是人们对现实世界事物的存在方式或运动状态的某种认识。表示信息的形式可以是数值、文字、图形、声音、图像及动画等。1.1.2 数据:数据是用于描述事物的某些属性的具体量值。1.1.......
  • Visual Studio 2022 如何在创建文件时生成默认代码以及注释文件操作
    在创建文件时生成默认代码对于已经有一定的c++编程基础的“学生”来说,次次写默认的代码有时候是挺浪费时间的,对于VisualStudio2022这个版本创建文件时生成默认代码的资源不多,今天先记录一下我们在下载visualstudio时需要下载Community、Packages、Shared这三个文件。我们需......
  • 【noip赛前20天冲刺集训 day4】正在出模拟赛
    题目描述想象学竞赛网站CodeFancy举办了\(m\)场比赛。你在CodeFancy上关注了\(n\)个账号,编号为\(1\)到\(n\)。你知道这\(n\)个账号分别参加了\(m\)场比赛中的哪些。但是你发现可能存在一个人使用多个账号的情况,你想知道这\(n\)个账号的使用者最少共有多少人。......
  • LeetCode Day02 977&209&59
    第一题是[977. 有序数组的平方]这题解题思路依旧可以用双指针,指针分别指向数组的头尾两端,然后对两端求乘积比较大小,把乘积值更大的存储到数组尾端,然后指针更新位置,代码如下。publicint[]sortedSquares(int[]nums){//res用于存储平方和结果int[]res=ne......
  • 2020-2021 ICPC, NERC, Southern and Volga Russian Regional Contest (Online Mirror
    有五种种类的垃圾,数量分别为\(a_1,a_2,a_3,a_4,a_5\)。第一种为纸质垃圾第二种为塑料垃圾第三种双非垃圾第四种基本纸质垃圾第五种基本塑料垃圾有三种垃圾桶,容量分别为\(c_1,c_2,c_3\)。第一种垃圾桶可以放入:纸质垃圾和基本纸质垃圾第二种垃圾桶可以放入:塑料......
  • 2023.10.9NOIPSIM1总结
    ##T1区分度先手算一下找下规律,发现数列呈现$1,2,2,3,3,4,4,4,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8......$的规律。数据范围到$1e13$,考虑数论分块,每块的块长由前一块块长递推得到。在块内累$\Omicron$(1)累计答案,跳块时间复杂度$\Omicron$($\sqrtn$),总复杂度$\Omicron(t\sqr......
  • 测试4 20211102尹子扬静态库的测试
    1.首先,编译你的模块源代码成为目标文件(.o文件)。例如,如果有一个模块名为mymath.c,你可以使用以下命令来生成目标文件:点击查看代码gcc-cmymath.c-omymath.o请确保你以适当的方式编译所有的模块源代码文件。2.将所有目标文件打包成一个静态库文件。你可以使用ar命令来......
  • 【2023年10月12日】stf61-MySQL数据库
     stf61-MySQL数据库前言1)为什么学?● 常见的笔试题● 有利于更好的开展测试工作2)学什么?理论:基本的术语和概念实操:数据库操作、表操作、数据操作、其他常见数据库功能3)怎么学?多在实训环境里练习,在练习中掌握 理论 数据库系统: 表:8条记录/行,6个字段/列 ......