Skip to content

Instantly share code, notes, and snippets.

@attgm
Created August 10, 2023 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save attgm/d479693ca765da7c4aebd0647878f666 to your computer and use it in GitHub Desktop.
Save attgm/d479693ca765da7c4aebd0647878f666 to your computer and use it in GitHub Desktop.
Solver for `Subtree` problem
use proconio::{input, marker::Usize1};
use itertools::Itertools;
#[derive(Clone)]
struct Node {
neighbors: Vec<usize>,
value: Vec<(usize, usize)>,
m: usize
}
impl Node {
fn new(m:usize) -> Self {
Node {
neighbors: vec![],
value: vec![],
m: m
}
}
fn add_neighbor(&mut self, i: usize) {
self.neighbors.push(i);
}
fn set_child_value(&mut self, id: usize, value:usize) -> usize {
if let Some(index) = self.neighbors.iter().position(|x| *x == id) {
self.neighbors.swap_remove(index);
self.value.push((id, value))
}
self.neighbors.len()
}
fn set_parent_node(&mut self) -> Option<usize> {
assert!(self.neighbors.len() <= 1);
if self.neighbors.len() == 1 {
Some(self.neighbors[0])
} else {
None
}
}
fn get_value(&self, parent: usize) -> usize {
self.value.iter()
.filter(|&&x| x.0 != parent)
.fold(1, |sum, x| (sum * (x.1 + 1)) % self.m)
}
fn get_answer(&self) -> usize {
self.value.iter()
.fold(1, |sum, x| (sum * (x.1 + 1)) % self.m)
}
}
fn main() {
input! {
n : usize, m : usize,
edges : [(Usize1, Usize1); n - 1]
}
let mut nodes: Vec<Node> = vec![Node::new(m); n];
for (i, j) in &edges {
nodes[*i].add_neighbor(*j);
nodes[*j].add_neighbor(*i);
}
let mut queue: Vec<_> = nodes.iter()
.positions(|node| node.neighbors.len() <= 1)
.collect();
let root = 'bottom_up_loop: loop {
let mut next_queue = Vec::new();
for &i in queue.iter() {
if let Some(parent) = nodes[i].set_parent_node() {
let value = nodes[i].get_value(parent);
if nodes[parent].set_child_value(i, value) == 1 {
next_queue.push(parent);
}
} else {
break 'bottom_up_loop i;
}
}
queue = next_queue;
assert!(queue.len() > 0);
};
let mut queue = vec![root];
'top_down_loop: loop {
let mut next_queue = Vec::new();
for &i in &queue {
for child in nodes[i].value.clone() {
let p = child.0;
if nodes[p].neighbors.len() > 0 {
next_queue.push(p);
}
let value = nodes[i].get_value(p);
let j = nodes[p].set_child_value(i, value);
assert!(j == 0);
}
}
if next_queue.len() == 0 {
break 'top_down_loop;
}
queue = next_queue;
};
for i in 0..n {
println!("{:?}", nodes[i].get_answer());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment