[题解] CF1245D - Shichikuji and Power Grid
1.[题解] CF1328E Tree Queries2.[题解] AtCoder Beginner Contest 308 A~G3.[题解] CF1526C2 Potions4.[题解] CF29D Ant on the Tree5.[题解] Codeforces Round 895 (Div. 3) F~G6.[题解} CF1217D Coloring Edges7.[题解] CF1873H - Mad City8.[题解] Codeforces Round 900(Div.3) E~F9.[题解] CF1882D - Tree XOR10.[题解] CF1003E - Tree Constructing11.[题解] CF632F - Swimmers in the Pool
12.[题解] CF1245D - Shichikuji and Power Grid
13.[题解] CF1790E - XOR TreeCF1245D - Shichikuji and Power Grid
题意
在一个网格图中,有
对于一个城市有电,要么选择在其位置建立发电站,要么和另一个有电的城市连线。
对于城市
问使得所有城市都通电的情况下,如何得到费用最小的方案。
思路
可以发现,图中连线实际上就是图的边,考虑到
现在考虑在哪里建电站比较好。我们可以假设只有一个额外地点建电站,那么在某个地方建电站,就转化为这个城市和这个额外地点连一条
考虑如何使得代价最小。因为我们上面的操作,现在已经有了一张带权无向图了。我们要使得
这里使用的是 Kruskal
算法,如果使用 Prime
实现,会更快一点。
实现
#![allow(dead_code)] #![allow(unused_variables)] #![allow(unused_imports)] use std::fmt::write; use std::io::{self, prelude::*, BufWriter}; use std::process::id; use std::{str, vec}; use std::cmp::Ordering; struct Scanner<R> { reader: R, buf_str: Vec<u8>, buf_iter: str::SplitAsciiWhitespace<'static>, } impl<R : io::BufRead> Scanner<R> { fn new(reader: R) -> Self { Self { reader, buf_str: Vec::new(), buf_iter: "".split_ascii_whitespace() } } fn next<T: str::FromStr>(&mut self) -> T { loop { if let Some(token) = self.buf_iter.next() { return token.parse().ok().expect("Failed parse"); } self.buf_str.clear(); self.reader.read_until(b'\n', &mut self.buf_str).expect("Failed read"); self.buf_iter = unsafe { let slice = str::from_utf8_unchecked(&self.buf_str); std::mem::transmute(slice.split_ascii_whitespace()) } } } } struct DisjointSet { leader : Vec<usize> } impl DisjointSet { fn new(n : usize) -> Self { let mut ret = Self { leader : vec![0; n] }; for (i, v) in ret.leader.iter_mut().enumerate() { *v = i; } return ret; } fn get_leader(&mut self, x : usize) -> usize { if self.leader[x] == x { return x; } else { let ret = self.get_leader(self.leader[x]); self.leader[x] = ret; return ret; } } fn merge_to(&mut self, from : usize, to : usize) -> bool { let f = self.get_leader(from); let t = self.get_leader(to); if f == t { return false; } self.leader[f] = t; return true; } fn merge_to_max(&mut self, a : usize, b : usize) -> bool { let mut fa = self.get_leader(a); let mut fb = self.get_leader(b); if fa == fb { return false; } else if fa > fb { std::mem::swap(&mut fa, &mut fb); } self.leader[fa] = fb; return true; } } fn main() { let (stdin, stdout) = (io::stdin(), io::stdout()); let mut scan = Scanner::new(stdin.lock()); let mut out = std::io::BufWriter::new(stdout.lock()); let n : usize = scan.next(); let mut point : Vec<(i64, i64)> = vec![(0,0); n]; for x in &mut point { x.0 = scan.next(); x.1 = scan.next(); } let mut vc : Vec<u64> = vec![0; n]; for x in &mut vc { *x = scan.next(); } let mut vk : Vec<u64> = vec![0; n]; for x in &mut vk { *x = scan.next(); } let mut edge : Vec<(u32, u32, u64)> = Vec::with_capacity(n * n + n); for (i, c) in vc.iter().enumerate() { edge.push((i as u32, n as u32, *c)); } for (i, u) in point.iter().enumerate() { for (j, v) in point.iter().enumerate() { let x = u.0 - v.0; let y = u.1 - v.1; edge.push((i as u32, j as u32, (vk[i as usize] + vk[j as usize]) * ((x.abs() + y.abs()) as u64))); } } edge.sort_by(|&a, &b| a.2.cmp(&b.2)); let mut dsu = DisjointSet::new(n + 1); let mut rete : Vec<(u32, u32)> = Vec::with_capacity(2 * n - 1); let mut retc : Vec<u32> = Vec::with_capacity(n); let mut cost : u64 = 0; for (u, v, w) in &edge { if dsu.merge_to(*u as usize, *v as usize) { cost += *w; if *v as usize >= n { retc.push(*u); } else { rete.push((*u, *v)); } } } write!(out, "{}\n{}\n", cost, retc.len()).unwrap(); for i in &retc { write!(out, "{} ", i + 1).unwrap(); } write!(out, "\n{}\n", rete.len()).unwrap(); for (u, v) in &rete { write!(out, "{} {}\n", u + 1, v + 1).unwrap(); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】