0

Dream giacmo

đã đăng vào 18, Tháng 4, 2026, 15:58

use std::io::{self, Read}; use std::cmp;

struct Graph { adj: Vec<Vec<(usize, i32)>>, visited: Vec<bool>, }

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(); }


Bình luận

Hãy đọc nội quy trước khi bình luận.


Không có bình luận tại thời điểm này.