QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#539579 | #8941. Even or Odd Spanning Tree | ucup-team635# | WA | 58ms | 9776kb | Rust | 5.2kb | 2024-08-31 15:09:17 | 2024-08-31 15:09:17 |
Judging History
answer
//---------- begin union_find ----------
#[derive(Clone)]
pub struct DSU {
p: Vec<i32>,
}
impl DSU {
pub fn new(n: usize) -> DSU {
assert!(n < std::i32::MAX as usize);
DSU { p: vec![-1; n] }
}
pub fn init(&mut self) {
self.p.iter_mut().for_each(|p| *p = -1);
}
pub fn root(&self, mut x: usize) -> usize {
assert!(x < self.p.len());
while self.p[x] >= 0 {
x = self.p[x] as usize;
}
x
}
pub fn same(&self, x: usize, y: usize) -> bool {
assert!(x < self.p.len() && y < self.p.len());
self.root(x) == self.root(y)
}
pub fn unite(&mut self, x: usize, y: usize) -> Option<(usize, usize)> {
assert!(x < self.p.len() && y < self.p.len());
let mut x = self.root(x);
let mut y = self.root(y);
if x == y {
return None;
}
if self.p[x] > self.p[y] {
std::mem::swap(&mut x, &mut y);
}
self.p[x] += self.p[y];
self.p[y] = x as i32;
Some((x, y))
}
pub fn parent(&self, x: usize) -> Option<usize> {
assert!(x < self.p.len());
let p = self.p[x];
if p >= 0 {
Some(p as usize)
} else {
None
}
}
pub fn sum<F>(&self, mut x: usize, mut f: F) -> usize
where
F: FnMut(usize),
{
while let Some(p) = self.parent(x) {
f(x);
x = p;
}
x
}
pub fn size(&self, x: usize) -> usize {
assert!(x < self.p.len());
let r = self.root(x);
(-self.p[r]) as usize
}
}
//---------- end union_find ----------
// ---------- begin scannner ----------
#[allow(dead_code)]
mod scanner {
use std::str::FromStr;
pub struct Scanner<'a> {
it: std::str::SplitWhitespace<'a>,
}
impl<'a> Scanner<'a> {
pub fn new(s: &'a String) -> Scanner<'a> {
Scanner {
it: s.split_whitespace(),
}
}
pub fn next<T: FromStr>(&mut self) -> T {
self.it.next().unwrap().parse::<T>().ok().unwrap()
}
pub fn next_bytes(&mut self) -> Vec<u8> {
self.it.next().unwrap().bytes().collect()
}
pub fn next_chars(&mut self) -> Vec<char> {
self.it.next().unwrap().chars().collect()
}
pub fn next_vec<T: FromStr>(&mut self, len: usize) -> Vec<T> {
(0..len).map(|_| self.next()).collect()
}
}
}
// ---------- end scannner ----------
use std::io::Write;
fn main() {
use std::io::Read;
let mut s = String::new();
std::io::stdin().read_to_string(&mut s).unwrap();
let mut sc = scanner::Scanner::new(&s);
let out = std::io::stdout();
let mut out = std::io::BufWriter::new(out.lock());
run(&mut sc, &mut out);
}
fn run<W: Write>(sc: &mut scanner::Scanner, out: &mut std::io::BufWriter<W>) {
let t: u32 = sc.next();
for _ in 0..t {
let n: usize = sc.next();
let m: usize = sc.next();
let mut e = vec![(0, 0, 0); m];
for e in e.iter_mut() {
e.0 = sc.next::<usize>() - 1;
e.1 = sc.next::<usize>() - 1;
e.2 = sc.next::<i64>();
}
let ans = solve(n, e);
writeln!(out, "{} {}", ans[0], ans[1]).ok();
}
}
fn solve(n: usize, mut e: Vec<(usize, usize, i64)>) -> [i64; 2] {
e.sort_by_key(|e| e.2);
let mut dsu = DSU::new(n);
let mut tree = vec![];
let mut test = vec![];
for (a, b, c) in e {
if dsu.unite(a, b).is_some() {
tree.push((a, b, c));
} else {
test.push((a, b, c));
}
}
if tree.len() + 1 != n {
return [-1; 2];
}
let tree = tree;
let s = tree.iter().map(|e| e.2).sum::<i64>();
let mut ans = [std::i64::MAX; 2];
ans[s as usize & 1] = s;
let mut dsu = vec![DSU::new(n); 2];
let mut memo = vec![];
for (i, dsu) in dsu.iter_mut().enumerate() {
let mut tree = tree.clone();
for e in tree.iter_mut() {
if e.2 % 2 != (i as i64) {
e.2 = 0;
}
}
tree.sort_by_key(|e| e.2);
let mut dp = vec![std::i64::MAX; n];
for (a, b, c) in tree {
let (_, x) = dsu.unite(a, b).unwrap();
dp[x] = c;
}
memo.push(dp);
}
let find = |mut x: usize, mut y: usize, p: usize| -> Option<i64> {
let memo = &memo[p];
let dsu = &dsu[p];
let mut ans = 0;
while x != y {
if memo[x] >= memo[y] {
std::mem::swap(&mut x, &mut y);
}
if memo[x] != 0 {
ans = ans.max(memo[x]);
}
x = dsu.parent(x).unwrap();
}
if ans != std::i64::MAX {
Some(ans)
} else {
None
}
};
let po = &mut ans[(s as usize ^ 1) & 1];
for (a, b, c) in test {
if let Some(w) = find(a, b, (c as usize ^ 1) & 1) {
*po = std::cmp::min(*po, s - w + c);
}
}
if *po == std::i64::MAX {
*po = -1;
}
ans
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 2036kb
input:
3 2 1 1 2 5 3 1 1 3 1 4 4 1 2 1 1 3 1 1 4 1 2 4 2
output:
-1 5 -1 -1 4 3
result:
ok 6 numbers
Test #2:
score: -100
Wrong Answer
time: 58ms
memory: 9776kb
input:
10000 16 50 1 2 649251632 2 3 605963017 3 4 897721528 4 5 82446151 5 6 917109168 6 7 79647183 7 8 278566178 7 9 573504723 3 10 679859251 8 11 563113083 1 12 843328546 10 13 594049160 11 14 997882839 7 15 569431750 2 16 244494799 16 7 960172373 13 4 317888322 13 3 446883598 9 3 678142319 5 8 43208692...
output:
3140067932 3159441841 1262790434 1309454727 1263932600 1307926149 1189242112 1180186165 2248358640 2261370885 3776889482 3738936375 1093500444 1058677117 3433711014 3402127725 1201099898 1187873655 1395482806 1410162043 3456885934 3486092007 3943951826 3988876469 2479987500 2535532661 2909126794 293...
result:
wrong answer 116th numbers differ - expected: '1207927187', found: '1120243322'