algorithm_2024/src/20241118/T541156_25pts.cpp
2024-11-19 18:47:13 +08:00

99 lines
3.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <cctype>
#include <cstdint>
#include <iostream>
#include <utility>
#include <vector>
#include <map>
using ll = int64_t;
using std::cin, std::cout;
// 定义最大节点数为5e5加5以确保足够的空间
const ll maxn = 5e5 + 5;
ll n, k; // n: 树的节点数k: 暴龙的种类数
ll a[maxn]; // a[i]: 第i个节点的暴龙种类
ll ans[maxn]; // ans[i]: 第i种暴龙的红温值
std::vector<std::pair<ll, ll>> adj[maxn]; // adj[u]: 节点u的邻居及边权
std::map<ll, ll> dp[maxn]; // dp[u][j]: 节点u到子树中种类j的最大距离
// 优化输入读取提高IO速度
struct CinNum {
char c;
ll n, w;
// 重载右移运算符以自定义输入方式
CinNum &operator>>(ll &num) {
c = n = 0;
w = 1;
// 跳过非数字字符,记录负号
while (!isdigit(c = getchar())) {
if (c == '-') w = -1;
}
// 读取数字
while (isdigit(c)) {
n = n * 10 + (c - '0');
c = getchar();
}
num = n * w;
return *this;
}
} cinn;
// 使用自定义的CinNum来替代标准输入
#define cin cinn
/**
* @brief 使用深度优先搜索 (DFS) 计算每种暴龙的红温值
*
* @param fth 当前节点的父节点
* @param u 当前处理的节点
*/
void dfs(const ll &fth, const ll &u) noexcept {
// 初始化当前节点的dp自己到自己距离为0
dp[u].emplace(a[u], 0);
// 遍历所有邻接节点
for (const auto& [v, w] : adj[u]) {
if (v == fth) continue; // 避免回到父节点
dfs(u, v); // 递归处理子节点
// 遍历子节点v的所有暴龙种类及其对应的最大距离
for (const auto& [kk, vv] : dp[v]) {
// 如果当前节点u已经有这种暴龙类型且子节点v也有
if ((dp[u][kk] > 0 || a[u] == kk) && (dp[v][kk] > 0 || a[v] == kk)) {
// 更新ans[kk]为u和v子树中这种暴龙类型的最大距离
ans[kk] = std::max(ans[kk], dp[u][kk] + dp[v][kk] + w);
}
// 更新u节点到这种暴龙类型的最大距离
dp[u][kk] = std::max(dp[u][kk], dp[v][kk] + w);
// 如果当前节点u本身就是这种暴龙类型进一步更新ans[kk]
if (a[u] == kk) {
ans[kk] = std::max(ans[kk], dp[u][kk]);
}
}
// 清空子节点v的dp以节省内存因为已经合并到u的dp中了
dp[v].clear();
}
}
int main(){
// 读取节点数n和暴龙种类数k
cin >> n >> k;
// 读取每个节点的暴龙种类
for(ll i = 1; i <= n; i++) cin >> a[i];
// 读取树的边信息,并构建邻接表
for(ll i = 1; i < n; i++){
ll u, v, w;
cin >> u >> v >> w;
adj[u].emplace_back(v, w);
adj[v].emplace_back(u, w);
}
// 从节点1开始DFS遍历整棵树假设节点1为根节点父节点为0
dfs(0, 1);
// 输出每种暴龙的红温值
for(ll i = 1; i <= k; i++) cout << ans[i] << '\n';
}