Dream giacmo
đã đăng vào 18, Tháng 4, 2026, 8:58use std::io::{self, Read}; use std::cmp;
struct Graph { adj: Vec<vec i32 visited: vec>, }</vec>
impl Graph { fn new(n: usize) -> Self { Graph { adj: vec![vec![]; n], visited: vec![false; n], } }
fn add_edge(&mut self, u: usize, v: usize, t: i32) {
self.adj[u].push((v, t));
self.adj[v].push((u, t));
}
// Trả về (nút xa nhất, khoảng cách, mảng cha để truy vết đường đi)
fn bfs(&self, start: usize, nodes_in_component: &mut Vec<usize>) -> (usize, i32, Vec<i32>, Vec<usize>) {
let mut dist = vec![-1; self.adj.len()];
let mut parent = vec![-1; self.adj.len()];
let mut path_nodes = Vec::new();
let mut queue = std::collections::VecDeque::new();
dist[start] = 0;
queue.push_back(start);
nodes_in_component.push(start);
let mut farthest_node = start;
let mut max_dist = 0;
while let Some(u) = queue.pop_front() {
if dist[u] > max_dist {
max_dist = dist[u];
farthest_node = u;
}
path_nodes.push(u);
for &(v, weight) in &self.adj[u] {
if dist[v] == -1 {
dist[v] = dist[u] + weight;
parent[v] = u as i32;
queue.push_back(v);
nodes_in_component.push(v);
}
}
}
(farthest_node, max_dist, parent, path_nodes)
}
// Tìm bán kính và đường kính của một thành phần liên thông
fn get_tree_stats(&mut self, start_node: usize) -> (i32, i32) {
let mut component = Vec::new();
// BFS 1: Tìm nút xa nhất A
let (node_a, _, _, _) = self.bfs(start_node, &mut component);
// Đánh dấu đã thăm các nút trong component này
for &node in &component { self.visited[node] = true; }
component.clear();
// BFS 2: Từ A tìm nút xa nhất B để xác định đường kính
let (node_b, diameter, parent, _) = self.bfs(node_a, &mut Vec::new());
// Truy vết đường kính để tìm bán kính tối ưu
let mut path = Vec::new();
let mut curr = node_b as i32;
while curr != -1 {
path.push(curr as usize);
curr = parent[curr as usize];
}
// Tính khoảng cách từ đầu A đến các nút trên đường kính
let mut dist_from_a = vec![0; path.len()];
let mut current_dist = 0;
for i in (0..path.len() - 1).rev() {
let u = path[i+1];
let v = path[i];
let weight = self.adj[u].iter().find(|&&(next, _)| next == v).unwrap().1;
current_dist += weight;
dist_from_a[path.len() - 1 - i] = current_dist;
}
// Bán kính R là giá trị nhỏ nhất của max(d(A, x), d(B, x)) với x thuộc đường kính
let mut radius = diameter;
for &d in &dist_from_a {
let max_to_end = cmp::max(d, diameter - d);
radius = cmp::min(radius, max_to_end);
}
(radius, diameter)
}
}
fn solve() { let mut input = String::new(); io::stdin().readtostring(&mut input).unwrap(); let mut tokens = input.split_whitespace();
let n: usize = tokens.next().unwrap().parse().unwrap();
let m: usize = tokens.next().unwrap().parse().unwrap();
let l: i32 = tokens.next().unwrap().parse().unwrap();
let mut graph = Graph::new(n);
for _ in 0..m {
let u: usize = tokens.next().unwrap().parse().unwrap();
let v: usize = tokens.next().unwrap().parse().unwrap();
let t: i32 = tokens.next().unwrap().parse().unwrap();
graph.add_edge(u, v, t);
}
let mut radii = Vec::new();
let mut max_diameter = 0;
for i in 0..n {
if !graph.visited[i] {
let (r, d) = graph.get_tree_stats(i);
radii.push(r);
max_diameter = cmp::max(max_diameter, d);
}
}
radii.sort_by(|a, b| b.cmp(a)); // Sắp xếp giảm dần
let mut ans = max_diameter;
if radii.len() >= 2 {
ans = cmp::max(ans, radii[0] + radii[1] + l);
}
if radii.len() >= 3 {
ans = cmp::max(ans, radii[1] + radii[2] + 2 * l);
}
println!("{}", ans);
}
fn main() { solve(); }