Submission #38441684


Source Code Expand

// -*- coding:utf-8-unix -*-
// rustup doc --std --toolchain 1.42.0

#![allow(unused_imports)]
#![allow(unused_macros)]
use bitset_fixed::BitSet;
use fixedbitset::Union;
use itertools::*;
use num::integer::*;
use petgraph::algo::*;
use petgraph::graph::{DiGraph, Graph, NodeIndex, UnGraph};
use petgraph::unionfind::UnionFind;
use petgraph::visit::{
    Bfs, Dfs, EdgeRef, IntoEdges, NodeCount, NodeIndexable, VisitMap, Visitable,
};
//use proconio::{input, marker::{Bytes, Chars, Isize1, Usize1}, source::{auto::AutoSource, line::LineSource, once::OnceSource}};
use rand::{
    distributions::WeightedIndex,
    prelude::{thread_rng, Distribution},
    seq::SliceRandom,
    Rng,
};
use regex::Regex;
use std::collections::*;
use std::io::{stderr, stdin, stdout, BufRead, BufReader, BufWriter, Read, Write};
use superslice::Ext;

pub fn solve() {
    //let tins = std::time::Instant::now();
    //let mut durs = Vec::with_capacity(16);
    use fastproconio::*;
    let stdin = std::io::stdin();
    let mut source = ProconIBufIter::new(stdin.lock());
    macro_rules! fread {
        ($t:tt) => {{
            fread_value!(source, $t)
        }};
    }
    macro_rules! finput {($($r:tt)*)=>{finput_inner!{source, $($r)*}};}
    let mut out = std::io::stdout();
    let mut obuf = ProconWriteBuffer::with_capacity(1 << 26);
    //durs.push((tins.elapsed(), String::from("initial")));
    //let mut out = std::io::BufWriter::new(out.lock());
    //let err = std::io::stderr();
    //let mut err = std::io::BufWriter::new(err.lock());
    finput! {
        n: usize, m: usize,
    }
    //durs.push((tins.elapsed(), String::from("input")));

    if n != m + 1 {
        obuf.bytes(b"No\n");
        obuf.write_all(&mut out);
        return;
    }

    let mut dsu = Dsu::new(n);
    let mut count: Vec<u8> = vec![0; n];
    let mut count_2p: u32 = 0;
    let mut count_3p: u32 = 0;

    for _ in 0..m {
        finput! {
            u: usize1, v: usize1,
        }
        dsu.merge(u, v);
        count[u] += 1;
        match count[u] {
            2 => {
                count_2p += 1;
            }
            3 => {
                count_3p += 1;
                break;
            }
            _ => {}
        }
        count[v] += 1;
        match count[v] {
            2 => {
                count_2p += 1;
            }
            3 => {
                count_3p += 1;
                break;
            }
            _ => {}
        }
    }

    obuf.bytes(if dsu.size(0) == n && count_2p == (n as u32) - 2 && count_3p == 0 {
        b"Yes\n"
    } else {
        b"No\n"
    });
    obuf.write_all(&mut out);
    //let _ = std::io::Write::flush(&mut out);
    //durs.push((tins.elapsed(), String::from("output")));
    //for (dur, s) in durs.iter() { eprintln!("{:.6} {}", dur.as_secs_f64(), s); }
    //let _ = writeln!(&mut err, "{}", count);
    //let _ = std::io::Write::flush(&mut err);
}

pub fn main() {
    const USE_THREAD: bool = false;
    if USE_THREAD {
        // In order to avoid potential stack overflow, spawn a new thread.
        let stack_size = 134_217_728; // 128 MB
        let thd = std::thread::Builder::new().stack_size(stack_size);
        thd.spawn(|| solve()).unwrap().join().unwrap();
    } else {
        solve()
    }
}

/// chmax, chmin sugar syntax
trait Change {
    fn chmax(&mut self, x: Self);
    fn chmin(&mut self, x: Self);
}
impl<T: PartialOrd> Change for T {
    fn chmax(&mut self, x: T) {
        if *self < x {
            *self = x;
        }
    }
    fn chmin(&mut self, x: T) {
        if *self > x {
            *self = x;
        }
    }
}
pub mod fastproconio {
    /// input macros based on tanakh's input macro / proconio-rs.
    /// tanakh's input macro: <https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8>
    /// proconio-rs: <https://docs.rs/proconio/0.3.8/proconio/>
    /// this macro recieve `Iterator<Item = u8>` input source, except for Bytes/Chars/String read
    /// ProconIBufIter receive `std::io::BufRead` trait. (`std::io::StdinLock`, `std::io::BufReader`, `&[u8]`, etc.)
    #[macro_export]
    macro_rules! finput_inner {
        ($iter:expr) => {};
        ($iter:expr, ) => {};
        ($iter:expr, mut $var:ident : $t:tt $($r:tt)*) => {
            let mut $var = fread_value!($iter, $t);
            finput_inner!{$iter $($r)*}
        };
        ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
            let $var = fread_value!($iter, $t);
            finput_inner!{$iter $($r)*}
        };
    }
    #[macro_export]
    macro_rules! fread_value {
        ($iter:expr, ( $($t:tt),* )) => { ( $(fread_value!($iter, $t)),* ) };
        ($iter:expr, [ $t:tt ; $len:expr ]) => { (0..$len).map(|_| fread_value!($iter, $t)).collect::<Vec<_>>() };
        ($iter:expr, u128) => { $iter.parse_uint::<u128>() };
        ($iter:expr, usize) => { $iter.parse_uint::<usize>() };
        ($iter:expr, usize1) => { $iter.parse_uint::<usize>() - 1 };
        ($iter:expr, u64) => { $iter.parse_uint::<u64>() };
        ($iter:expr, u64_1) => { $iter.parse_uint::<u64>() - 1 };
        ($iter:expr, u32) => { $iter.parse_uint::<u32>() };
        ($iter:expr, u32_1) => { $iter.parse_uint::<u32>() - 1 };
        ($iter:expr, u16) => { $iter.parse_uint::<u16>() };
        ($iter:expr, u8) => { $iter.parse_uint::<u8>() };
        ($iter:expr, i128) => { $iter.parse_iint::<i128>() };
        ($iter:expr, isize) => { $iter.parse_iint::<isize>() };
        ($iter:expr, i64) => { $iter.parse_iint::<i64>() };
        ($iter:expr, i32) => { $iter.parse_iint::<i32>() };
        ($iter:expr, i16) => { $iter.parse_iint::<i16>() };
        ($iter:expr, i8) => { $iter.parse_iint::<i16>() as i8 };
        ($iter:expr, byte) => { $iter.get_ascii_byte() };
        ($iter:expr, Bytes) => {{ let mut v = vec![];$iter.get_ascii_bytes(&mut v);v }};
        ($iter:expr, Chars) => {{ let mut v = vec![];$iter.get_ascii_chars(&mut v);v }};
        ($iter:expr, String) => {{ let mut v = vec![];$iter.get_ascii_bytes(&mut v);unsafe { std::string::String::from_utf8_unchecked(v) }}};
        ($iter:expr, LineBytes) => {{ let mut v = vec![];$iter.get_ascii_line_bytes(&mut v).and(Some(v)).unwrap() }};
        ($iter:expr, LineBytesTrim) => {{ let mut v = vec![];$iter.get_ascii_line_bytes_trim(&mut v);v }};
        ($iter:expr, LineString) => {{ let mut v = vec![];$iter.get_ascii_line_bytes(&mut v);unsafe { std::string::String::from_utf8_unchecked(v) }}};
        ($iter:expr, LineStringTrim) => {{ let mut v = vec![];$iter.get_ascii_line_bytes_trim(&mut v);unsafe { std::string::String::from_utf8_unchecked(v) }}};
        ($iter:expr, Utf8Bytes) => {{ let mut v = vec![];$iter.get_utf8_bytes(&mut v);v }};
        ($iter:expr, Utf8String) => {{ let mut v = vec![];$iter.get_utf8_bytes(&mut v);unsafe { std::string::String::from_utf8_unchecked(v) }}};
        ($iter:expr, Utf8LineBytes) => {{ let mut v = vec![];$iter.get_utf8_line_bytes(&mut v);v }};
        ($iter:expr, Utf8LineBytesTrim) => {{ let mut v = vec![];$iter.get_utf8_line_bytes_trim(&mut v);v }};
        ($iter:expr, Utf8LineString) => {{ let mut v = vec![];$iter.get_utf8_line_bytes(&mut v);unsafe { std::string::String::from_utf8_unchecked(v) }}};
        ($iter:expr, Utf8LineStringTrim) => {{ let mut v = vec![];$iter.get_utf8_line_bytes_trim(&mut v);unsafe { std::string::String::from_utf8_unchecked(v) }}};
        ($iter:expr, $t:ty) => {{ let mut v = vec![];unsafe { std::string::String::from_utf8_unchecked($iter.get_utf8_bytes(&mut v).and(Some(v)).unwrap()) }.parse::<$t>().expect("Parse error") }};
    }

    /// Interaction with `std::io::BufRead` Trait, Implementation of `Iterator<Item = u8>`
    pub struct ProconIBufIter<R: std::io::BufRead> {
        inner: R,
        raw: *const u8,
        len: usize,
        ptr: *const u8,
        end: *const u8,
    }
    unsafe fn ptr_offset_u8(dist: *const u8, origin: *const u8) -> usize {
        // Rust 1.47.0 or later, `dist.offset_from(origin) as usize`
        // <https://doc.rust-lang.org/std/primitive.pointer.html#method.offset_from>
        dist as usize - origin as usize
    }
    impl<R: std::io::BufRead> ProconIBufIter<R> {
        /// consume raw buffer
        #[allow(unused)]
        fn consume(&mut self, amt: usize) {
            let remain = unsafe { ptr_offset_u8(self.end, self.ptr) };
            assert!(remain >= amt);
            unsafe {
                self.ptr = self.ptr.add(amt);
            }
        }
        /// read when buffer is empty
        unsafe fn inner_read(&mut self) -> bool {
            assert!(self.is_empty());
            self.inner.consume(self.len);
            let buffer = self.inner.fill_buf().unwrap();
            let raw = buffer.as_ptr();
            let len = buffer.len();
            self.raw = raw;
            self.len = len;
            self.ptr = raw;
            self.end = raw.add(len);
            self.len > 0
        }
        /// check end of buffer
        fn is_empty(&self) -> bool {
            self.ptr == self.end
        }
        /// Interaction with `std::io::BufRead` Trait, Implementation of `Iterator<Item = u8>`
        pub fn new(inner: R) -> Self {
            Self {
                inner,
                raw: std::ptr::null(),
                len: 0,
                ptr: std::ptr::null(),
                end: std::ptr::null(),
            }
        }
        /// next(), but return empty value
        #[allow(unused)]
        fn next_unread(&mut self) -> Option<()> {
            if self.is_empty() && unsafe { !self.inner_read() } {
                return None;
            }
            unsafe {
                self.ptr = self.ptr.add(1);
            }
            return Some(());
        }
        /// get now pointer & increment pointer
        unsafe fn next_unchecked(&mut self) -> u8 {
            let p = self.ptr;
            self.ptr = p.add(1);
            *p
        }
        /// peek
        #[allow(unused)]
        fn peek(&mut self) -> Option<&u8> {
            if !self.is_empty() || unsafe { self.inner_read() } {
                unsafe { Some(&*self.ptr) }
            } else {
                None
            }
        }
        /// raw buffer
        #[allow(unused)]
        fn raw_buf(&mut self) -> &[u8] {
            if self.is_empty() {
                unsafe {
                    self.inner_read();
                }
            }
            unsafe { std::slice::from_raw_parts(self.ptr, ptr_offset_u8(self.end, self.ptr)) }
        }
        /// skip unmatch bytes
        pub fn skipuntil_bytes_fn<F: FnMut(u8) -> bool>(&mut self, f: &mut F) -> bool {
            loop {
                let mut ptr = self.ptr;
                while ptr != self.end {
                    if f(unsafe { *ptr }) {
                        self.ptr = ptr;
                        return true;
                    }
                    unsafe {
                        ptr = ptr.add(1);
                    }
                }
                self.ptr = ptr;
                if unsafe { !self.inner_read() } {
                    return false;
                }
            }
        }
    }
    impl<R: std::io::BufRead> Iterator for ProconIBufIter<R> {
        type Item = u8;
        /// fetch next byte
        fn next(&mut self) -> Option<Self::Item> {
            if !self.is_empty() || unsafe { self.inner_read() } {
                unsafe { Some(self.next_unchecked()) }
            } else {
                None
            }
        }
        /// remain size hint
        fn size_hint(&self) -> (usize, Option<usize>) {
            (unsafe { ptr_offset_u8(self.end, self.ptr) }, None)
        }
    }
    impl<R: std::io::BufRead> Drop for ProconIBufIter<R> {
        /// Saving the pointer on interruption
        fn drop(&mut self) {
            self.inner
                .consume(unsafe { ptr_offset_u8(self.ptr, self.raw) });
        }
    }
    /// speed frenzy input parser for program compete (fail parse may cause undefined behavior)
    pub trait ProconParse {
        /// parse unsigned integer
        fn parse_uint<
            U: Copy
                + std::cmp::Ord
                + std::ops::BitAnd<Output = U>
                + std::ops::Add<Output = U>
                + std::ops::Sub<Output = U>
                + std::ops::Mul<Output = U>
                + std::convert::From<u8>,
        >(
            &mut self,
        ) -> U;
        /// parse signed integer
        fn parse_iint<
            I: Copy
                + std::cmp::Ord
                + std::ops::BitAnd<Output = I>
                + std::ops::Add<Output = I>
                + std::ops::Sub<Output = I>
                + std::ops::Mul<Output = I>
                + std::convert::From<u8>
                + std::ops::Neg<Output = I>,
        >(
            &mut self,
        ) -> I;
        /// get char (printable ascii char)
        fn parse_byte(&mut self) -> u8;
        /// get chars (printable ascii word)
        fn parse_bytes(&mut self) -> Vec<u8>;
        /// get line chars (sp+printable ascii)
        fn parse_line_bytes(&mut self) -> Vec<u8>;
        /// get line chars (trimed sp+printable ascii)
        fn parse_line_bytes_trim(&mut self) -> Vec<u8>;
    }
    /// speed frenzy input byte reader for program compete
    pub trait ProconBytes {
        /// get bytes
        fn get_bytes_fn<F: Fn(u8) -> bool>(&mut self, vec: &mut Vec<u8>, f: &mut F);
        /// get chars
        fn get_ascii_chars_fn<F: Fn(u8) -> bool>(&mut self, vec: &mut Vec<char>, f: &mut F);
        /// get byte (printable ascii char)
        fn get_ascii_byte(&mut self) -> u8;
        /// get bytes (printable ascii word)
        fn get_ascii_bytes(&mut self, vec: &mut Vec<u8>);
        /// get chars (printable ascii word)
        fn get_ascii_chars(&mut self, vec: &mut Vec<char>);
        /// get line bytes (sp+printable ascii)
        fn get_ascii_line_bytes(&mut self, vec: &mut Vec<u8>);
        /// get line bytes (trimed sp+printable ascii)
        fn get_ascii_line_bytes_trim(&mut self, vec: &mut Vec<u8>);
        /// get bytes (printable utf8 word)
        fn get_utf8_bytes(&mut self, vec: &mut Vec<u8>);
        /// get line bytes (sp+printable utf8)
        fn get_utf8_line_bytes(&mut self, vec: &mut Vec<u8>);
        /// get line bytes (trimed sp+printable utf8)
        fn get_utf8_line_bytes_trim(&mut self, vec: &mut Vec<u8>);
    }
    impl<T: Iterator<Item = u8>> ProconParse for T {
        fn parse_uint<
            U: Copy
                + std::cmp::Ord
                + std::ops::BitAnd<Output = U>
                + std::ops::Add<Output = U>
                + std::ops::Sub<Output = U>
                + std::ops::Mul<Output = U>
                + std::convert::From<u8>,
        >(
            &mut self,
        ) -> U {
            loop {
                match self.next() {
                    Some(c @ b'0'..=b'9') => {
                        let mut x = U::from(c.wrapping_sub(b'0'));
                        while let Some(c @ b'0'..=b'9') = self.next() {
                            x = x.mul(U::from(10)).add(U::from(c.wrapping_sub(b'0')));
                        }
                        break x;
                    }
                    Some(_) => continue,
                    None => unreachable!(),
                }
            }
        }
        fn parse_iint<
            I: Copy
                + std::cmp::Ord
                + std::ops::BitAnd<Output = I>
                + std::ops::Add<Output = I>
                + std::ops::Sub<Output = I>
                + std::ops::Mul<Output = I>
                + std::ops::Neg<Output = I>
                + std::convert::From<u8>,
        >(
            &mut self,
        ) -> I {
            loop {
                match self.next() {
                    Some(c @ b'0'..=b'9') => {
                        let mut x = I::from(c.wrapping_sub(b'0'));
                        while let Some(c @ b'0'..=b'9') = self.next() {
                            x = x.mul(I::from(10)).add(I::from(c.wrapping_sub(b'0')));
                        }
                        break x;
                    }
                    Some(b'-') => {
                        let mut x = if let Some(c @ b'0'..=b'9') = self.next() {
                            I::from(c.wrapping_sub(b'0')).neg()
                        } else {
                            unreachable!();
                        };
                        while let Some(c @ b'0'..=b'9') = self.next() {
                            x = x.mul(I::from(10)).sub(I::from(c.wrapping_sub(b'0')));
                        }
                        break x;
                    }
                    Some(_) => continue,
                    None => unreachable!(),
                }
            }
        }
        fn parse_byte(&mut self) -> u8 {
            loop {
                match self.next() {
                    Some(c @ b'!'..=b'~') => break c,
                    Some(_) => continue,
                    None => break b'\0',
                }
            }
        }
        fn parse_bytes(&mut self) -> Vec<u8> {
            let mut v = vec![];
            loop {
                match self.next() {
                    Some(c @ b'!'..=b'~') => {
                        v.push(c);
                        while let Some(c @ b'!'..=b'~') = self.next() {
                            v.push(c);
                        }
                        break v;
                    }
                    Some(_) => continue,
                    None => break v,
                }
            }
        }
        fn parse_line_bytes(&mut self) -> Vec<u8> {
            let mut v = vec![];
            loop {
                match self.next() {
                    Some(c @ b' '..=b'~') => {
                        v.push(c);
                        while let Some(c @ b' '..=b'~') = self.next() {
                            v.push(c);
                        }
                        break v;
                    }
                    Some(_) => continue,
                    None => break v,
                }
            }
        }
        fn parse_line_bytes_trim(&mut self) -> Vec<u8> {
            let mut v = vec![];
            loop {
                match self.next() {
                    Some(c @ b'!'..=b'~') => {
                        v.push(c);
                        while let Some(c @ b' '..=b'~') = self.next() {
                            v.push(c);
                        }
                        while v.last() == Some(&b' ') {
                            v.pop();
                        }
                        break v;
                    }
                    Some(_) => continue,
                    None => break v,
                }
            }
        }
    }
    impl<R: std::io::BufRead> ProconBytes for ProconIBufIter<R> {
        /// get bytes vector
        fn get_bytes_fn<F: Fn(u8) -> bool>(&mut self, vec: &mut Vec<u8>, f: &mut F) {
            if !self.skipuntil_bytes_fn(f) {
                return;
            }
            let begin_ptr = self.ptr;
            let mut ptr = self.ptr;
            loop {
                unsafe {
                    ptr = ptr.add(1);
                }
                if ptr == self.end {
                    self.ptr = ptr;
                    vec.extend_from_slice(unsafe {
                        std::slice::from_raw_parts(begin_ptr, ptr_offset_u8(ptr, begin_ptr))
                    });
                    break;
                }
                if !f(unsafe { *ptr }) {
                    self.ptr = ptr;
                    vec.extend_from_slice(unsafe {
                        std::slice::from_raw_parts(begin_ptr, ptr_offset_u8(ptr, begin_ptr))
                    });
                    return;
                }
            }
            if unsafe { !self.inner_read() } {
                return;
            }
            ptr = self.ptr;
            loop {
                if !f(unsafe { *ptr }) {
                    self.ptr = ptr;
                    vec.extend_from_slice(unsafe {
                        std::slice::from_raw_parts(self.raw, ptr_offset_u8(ptr, self.raw))
                    });
                    return;
                }
                unsafe {
                    ptr = ptr.add(1);
                }
                if ptr == self.end {
                    self.ptr = ptr;
                    vec.extend_from_slice(unsafe {
                        std::slice::from_raw_parts(self.raw, self.len)
                    });
                    if unsafe { !self.inner_read() } {
                        return;
                    }
                    ptr = self.ptr;
                }
            }
        }
        fn get_ascii_chars_fn<F: Fn(u8) -> bool>(&mut self, vec: &mut Vec<char>, f: &mut F) {
            if !self.skipuntil_bytes_fn(f) {
                return;
            }
            let begin_ptr = self.ptr;
            let mut ptr = self.ptr;
            loop {
                unsafe {
                    ptr = ptr.add(1);
                }
                if ptr == self.end {
                    self.ptr = ptr;
                    let len = unsafe { ptr_offset_u8(ptr, begin_ptr) };
                    vec.reserve(len);
                    let mut p = begin_ptr;
                    while p != ptr {
                        vec.push(unsafe { *p } as char);
                        p = unsafe { p.add(1) };
                    }
                    break;
                }
                if !f(unsafe { *ptr }) {
                    self.ptr = ptr;
                    let len = unsafe { ptr_offset_u8(ptr, begin_ptr) };
                    vec.reserve(len);
                    let mut p = begin_ptr;
                    while p != ptr {
                        vec.push(unsafe { *p } as char);
                        p = unsafe { p.add(1) };
                    }
                    return;
                }
            }
            if unsafe { !self.inner_read() } {
                return;
            }
            ptr = self.ptr;
            loop {
                if !f(unsafe { *ptr }) {
                    self.ptr = ptr;
                    let len = unsafe { ptr_offset_u8(ptr, self.raw) };
                    vec.reserve(len);
                    let mut p = self.raw;
                    while p != ptr {
                        vec.push(unsafe { *p } as char);
                        p = unsafe { p.add(1) };
                    }
                    return;
                }
                unsafe {
                    ptr = ptr.add(1);
                }
                if ptr == self.end {
                    self.ptr = ptr;
                    let len = unsafe { ptr_offset_u8(ptr, self.raw) };
                    vec.reserve(len);
                    let mut p = self.raw;
                    while p != ptr {
                        vec.push(unsafe { *p } as char);
                        p = unsafe { p.add(1) };
                    }
                    if unsafe { !self.inner_read() } {
                        return;
                    }
                    ptr = self.ptr;
                }
            }
        }
        fn get_ascii_byte(&mut self) -> u8 {
            loop {
                match self.next() {
                    Some(c @ b'!'..=b'~') => break c,
                    Some(_) => continue,
                    None => break b'\0',
                }
            }
        }
        fn get_ascii_bytes(&mut self, vec: &mut Vec<u8>) {
            self.get_bytes_fn(vec, &mut |c| (b'!'..=b'~').contains(&c))
        }
        fn get_ascii_chars(&mut self, vec: &mut Vec<char>) {
            self.get_ascii_chars_fn(vec, &mut |c| (b'!'..=b'~').contains(&c))
        }
        fn get_ascii_line_bytes(&mut self, vec: &mut Vec<u8>) {
            self.get_bytes_fn(vec, &mut |c| (b' '..=b'~').contains(&c))
        }
        fn get_ascii_line_bytes_trim(&mut self, vec: &mut Vec<u8>) {
            self.skipuntil_bytes_fn(&mut |c| (b'!'..=b'~').contains(&c));
            self.get_bytes_fn(vec, &mut |c| (b' '..=b'~').contains(&c));
            while vec.last() == Some(&b' ') {
                vec.pop();
            }
        }
        fn get_utf8_bytes(&mut self, vec: &mut Vec<u8>) {
            self.get_bytes_fn(vec, &mut |c| (b'!'..=0xf4).contains(&c))
        }
        fn get_utf8_line_bytes(&mut self, vec: &mut Vec<u8>) {
            self.get_bytes_fn(vec, &mut |c| (b' '..=0xf4).contains(&c))
        }
        fn get_utf8_line_bytes_trim(&mut self, vec: &mut Vec<u8>) {
            self.skipuntil_bytes_fn(&mut |c| (b'!'..=0xf4).contains(&c));
            self.get_bytes_fn(vec, &mut |c| (b' '..=0xf4).contains(&c));
            while vec.last() == Some(&b' ') {
                vec.pop();
            }
        }
    }
    /// Insufficient write buffer size causes undefined operation.
    pub struct ProconWriteBuffer(*mut u8, Vec<u8>);
    impl ProconWriteBuffer {
        pub fn with_capacity(capacity: usize) -> Self {
            let mut b = Vec::<u8>::with_capacity(capacity);
            let ptr = b.as_mut_ptr();
            Self(ptr, b)
        }
        pub fn get_mut_ptr(&self) -> *mut u8 {
            self.0
        }
        pub fn set_mut_ptr(&mut self, p: *mut u8) {
            self.0 = p;
        }
        fn decision(&mut self) {
            let bptr = self.1.as_mut_ptr();
            unsafe { self.1.set_len((self.0 as usize) - (bptr as usize)) };
        }
        pub fn reserve(&mut self, additional: usize) {
            self.decision();
            self.1.reserve(additional);
            self.0 = self.1.as_mut_ptr();
        }
        pub fn reserve_exact(&mut self, additional: usize) {
            self.decision();
            self.1.reserve_exact(additional);
            self.0 = self.1.as_mut_ptr();
        }
        pub fn uint<U>(&mut self, d: U)
        where
            U: Copy
                + std::cmp::Ord
                + std::ops::Div<Output = U>
                + std::ops::Rem<Output = U>
                + std::convert::From<u8>
                + std::convert::Into<u128>,
        {
            proconwritebuf_uint(&mut self.0, d);
        }
        pub fn uint_sp<U>(&mut self, s: &[U])
        where
            U: Copy
                + std::cmp::Ord
                + std::ops::Div<Output = U>
                + std::ops::Rem<Output = U>
                + std::convert::From<u8>
                + std::convert::Into<u128>,
        {
            let mut p = self.0;
            let mut it = s.iter();
            if let Some(&d) = it.next() {
                proconwritebuf_uint(&mut p, d);
                for &d in it {
                    proconwritebuf_sp(&mut p);
                    proconwritebuf_uint(&mut p, d);
                }
            }
            self.0 = p;
        }
        pub fn uint_splf<U>(&mut self, s: &[U])
        where
            U: Copy
                + std::cmp::Ord
                + std::ops::Div<Output = U>
                + std::ops::Rem<Output = U>
                + std::convert::From<u8>
                + std::convert::Into<u128>,
        {
            let mut p = self.0;
            let mut it = s.iter();
            if let Some(&d) = it.next() {
                proconwritebuf_uint(&mut p, d);
                for &d in it {
                    proconwritebuf_sp(&mut p);
                    proconwritebuf_uint(&mut p, d);
                }
            }
            proconwritebuf_lf(&mut p);
            self.0 = p;
        }
        pub fn usize(&mut self, d: usize) {
            proconwritebuf_uint(&mut self.0, d as u64);
        }
        pub fn usize_sp(&mut self, s: &[usize]) {
            let mut p = self.0;
            let mut it = s.iter();
            if let Some(&d) = it.next() {
                proconwritebuf_uint(&mut p, d as u64);
                for &d in it {
                    proconwritebuf_sp(&mut p);
                    proconwritebuf_uint(&mut p, d as u64);
                }
            }
            self.0 = p;
        }
        pub fn usize_splf(&mut self, s: &[usize]) {
            let mut p = self.0;
            let mut it = s.iter();
            if let Some(&d) = it.next() {
                proconwritebuf_uint(&mut p, d as u64);
                for &d in it {
                    proconwritebuf_sp(&mut p);
                    proconwritebuf_uint(&mut p, d as u64);
                }
            }
            proconwritebuf_lf(&mut p);
            self.0 = p;
        }
        pub fn iint<I>(&mut self, d: I)
        where
            I: Copy
                + std::cmp::Ord
                + std::ops::Neg<Output = I>
                + std::ops::Div<Output = I>
                + std::ops::Rem<Output = I>
                + std::convert::From<i8>
                + std::convert::Into<i128>,
        {
            proconwritebuf_iint(&mut self.0, d);
        }
        pub fn iint_sp<I>(&mut self, s: &[I])
        where
            I: Copy
                + std::cmp::Ord
                + std::ops::Neg<Output = I>
                + std::ops::Div<Output = I>
                + std::ops::Rem<Output = I>
                + std::convert::From<i8>
                + std::convert::Into<i128>,
        {
            let mut p = self.0;
            let mut it = s.iter();
            if let Some(&d) = it.next() {
                proconwritebuf_iint(&mut p, d);
                for &d in it {
                    proconwritebuf_sp(&mut p);
                    proconwritebuf_iint(&mut p, d);
                }
            }
            self.0 = p;
        }
        pub fn iint_splf<I>(&mut self, s: &[I])
        where
            I: Copy
                + std::cmp::Ord
                + std::ops::Neg<Output = I>
                + std::ops::Div<Output = I>
                + std::ops::Rem<Output = I>
                + std::convert::From<i8>
                + std::convert::Into<i128>
                + std::convert::TryInto<u8>,
        {
            let mut p = self.0;
            let mut it = s.iter();
            if let Some(&d) = it.next() {
                proconwritebuf_iint(&mut p, d);
                for &d in it {
                    proconwritebuf_sp(&mut p);
                    proconwritebuf_iint(&mut p, d);
                }
            }
            proconwritebuf_lf(&mut p);
            self.0 = p;
        }
        pub fn sp(&mut self) {
            proconwritebuf_sp(&mut self.0);
        }
        pub fn lf(&mut self) {
            proconwritebuf_lf(&mut self.0);
        }
        pub fn bytes(&mut self, s: &[u8]) {
            proconwritebuf_bytes(&mut self.0, s);
        }
        pub fn str(&mut self, s: &str) {
            proconwritebuf_str(&mut self.0, s);
        }
        pub fn string(&mut self, s: &String) {
            proconwritebuf_string(&mut self.0, s);
        }
        pub fn write_all<W>(&mut self, out: &mut W)
        where
            W: std::io::Write,
        {
            self.decision();
            let _ = out.write_all(self.1.as_slice());
            self.1.clear();
            self.0 = self.1.as_mut_ptr();
        }
    }
    pub fn proconwritebuf_uint<U>(p: &mut *mut u8, mut d: U)
    where
        U: Copy
            + std::cmp::Ord
            + std::ops::Div<Output = U>
            + std::ops::Rem<Output = U>
            + std::convert::From<u8>
            + std::convert::Into<u128>,
    {
        unsafe {
            let bptr = *p;
            let mut cptr = bptr;
            if d != U::from(0) {
                while d != U::from(0) {
                    let (q, r) = (d / U::from(10), d % U::from(10));
                    d = q;
                    *cptr = b'0' + U::into(r) as u8;
                    cptr = cptr.add(1);
                }
                *p = cptr;
                let mut lptr = bptr;
                let mut rptr = cptr.sub(1);
                while (lptr as usize) < (rptr as usize) {
                    let (dr, dl) = (*lptr, *rptr);
                    *lptr = dl;
                    *rptr = dr;
                    lptr = lptr.add(1);
                    rptr = rptr.sub(1);
                }
            } else {
                *cptr = b'0';
                *p = cptr.add(1);
            }
        };
    }
    pub fn proconwritebuf_iint<I>(p: &mut *mut u8, mut d: I)
    where
        I: Copy
            + std::cmp::Ord
            + std::ops::Neg<Output = I>
            + std::ops::Div<Output = I>
            + std::ops::Rem<Output = I>
            + std::convert::From<i8>
            + std::convert::Into<i128>,
    {
        unsafe {
            let bptr = *p;
            let mut cptr = bptr;
            if d > I::from(0) {
                while d != I::from(0) {
                    let (q, r) = (d / I::from(10), d % I::from(10));
                    d = q;
                    *cptr = b'0' + I::into(r) as u8;
                    cptr = cptr.add(1);
                }
                *p = cptr;
                let mut lptr = bptr;
                let mut rptr = cptr.sub(1);
                while (lptr as usize) < (rptr as usize) {
                    let (dr, dl) = (*lptr, *rptr);
                    *lptr = dl;
                    *rptr = dr;
                    lptr = lptr.add(1);
                    rptr = rptr.sub(1);
                }
            } else if d < I::from(0) {
                *cptr = b'-';
                cptr = cptr.add(1);
                let mptr = cptr;
                {
                    let (q, r) = (-(d / I::from(10)), -(d % I::from(10)));
                    d = q;
                    *cptr = b'0' + I::into(r) as u8;
                    cptr = cptr.add(1);
                }
                while d != I::from(0) {
                    let (q, r) = (d / I::from(10), d % I::from(10));
                    d = q;
                    *cptr = b'0' + I::into(r) as u8;
                    cptr = cptr.add(1);
                }
                *p = cptr;
                let mut lptr = mptr;
                let mut rptr = cptr.sub(1);
                while (lptr as usize) < (rptr as usize) {
                    let (dr, dl) = (*lptr, *rptr);
                    *lptr = dl;
                    *rptr = dr;
                    lptr = lptr.add(1);
                    rptr = rptr.sub(1);
                }
            } else {
                *cptr = b'0';
                *p = cptr.add(1);
            }
        };
    }
    pub fn proconwritebuf_sp(p: &mut *mut u8) {
        *p = unsafe {
            **p = b' ';
            (*p).add(1)
        }
    }
    pub fn proconwritebuf_lf(p: &mut *mut u8) {
        *p = unsafe {
            **p = b'\n';
            (*p).add(1)
        }
    }
    pub fn proconwritebuf_bytes(p: &mut *mut u8, bytes: &[u8]) {
        *p = unsafe {
            let len = bytes.len();
            std::ptr::copy_nonoverlapping(bytes.as_ptr(), *p, len);
            (*p).add(len)
        };
    }
    pub fn proconwritebuf_str(p: &mut *mut u8, s: &str) {
        *p = unsafe {
            let len = s.len();
            std::ptr::copy_nonoverlapping(s.as_ptr(), *p, len);
            (*p).add(len)
        };
    }
    pub fn proconwritebuf_string(p: &mut *mut u8, s: &String) {
        *p = unsafe {
            let len = s.len();
            std::ptr::copy_nonoverlapping(s.as_ptr(), *p, len);
            (*p).add(len)
        };
    }
}

//https://github.com/rust-lang-ja/ac-library-rs

pub mod dsu {
    //! A Disjoint set union (DSU) with union by size and path compression.

    /// A Disjoint set union (DSU) with union by size and path compression.
    ///
    /// See: [Zvi Galil and Giuseppe F. Italiano, Data structures and algorithms for disjoint set union problems](https://core.ac.uk/download/pdf/161439519.pdf)
    ///
    /// In the following documentation, let $n$ be the size of the DSU.
    ///
    /// # Example
    ///
    /// ```
    /// use ac_library_rs::Dsu;
    /// use proconio::{input, source::once::OnceSource};
    ///
    /// input! {
    ///     from OnceSource::from(
    ///         "5\n\
    ///          3\n\
    ///          0 1\n\
    ///          2 3\n\
    ///          3 4\n",
    ///     ),
    ///     n: usize,
    ///     abs: [(usize, usize)],
    /// }
    ///
    /// let mut dsu = Dsu::new(n);
    /// for (a, b) in abs {
    ///     dsu.merge(a, b);
    /// }
    ///
    /// assert!(dsu.same(0, 1));
    /// assert!(!dsu.same(1, 2));
    /// assert!(dsu.same(2, 4));
    ///
    /// assert_eq!(
    ///     dsu.groups()
    ///         .into_iter()
    ///         .map(|mut group| {
    ///             group.sort_unstable();
    ///             group
    ///         })
    ///         .collect::<Vec<_>>(),
    ///     [&[0, 1][..], &[2, 3, 4][..]],
    /// );
    /// ```
    pub struct Dsu {
        n: usize,
        // root node: -1 * component size
        // otherwise: parent
        parent_or_size: Vec<i32>,
    }

    impl Dsu {
        /// Creates a new `Dsu`.
        ///
        /// # Constraints
        ///
        /// - $0 \leq n \leq 10^8$
        ///
        /// # Complexity
        ///
        /// - $O(n)$
        pub fn new(size: usize) -> Self {
            Self {
                n: size,
                parent_or_size: vec![-1; size],
            }
        }

        // `\textsc` does not work in KaTeX
        /// Performs the Uɴɪᴏɴ operation.
        ///
        /// # Constraints
        ///
        /// - $0 \leq a < n$
        /// - $0 \leq b < n$
        ///
        /// # Panics
        ///
        /// Panics if the above constraints are not satisfied.
        ///
        /// # Complexity
        ///
        /// - $O(\alpha(n))$ amortized
        pub fn merge(&mut self, a: usize, b: usize) -> usize {
            assert!(a < self.n);
            assert!(b < self.n);
            let (mut x, mut y) = (self.leader(a), self.leader(b));
            if x == y {
                return x;
            }
            if -self.parent_or_size[x] < -self.parent_or_size[y] {
                std::mem::swap(&mut x, &mut y);
            }
            self.parent_or_size[x] += self.parent_or_size[y];
            self.parent_or_size[y] = x as i32;
            x
        }

        /// Returns whether the vertices $a$ and $b$ are in the same connected component.
        ///
        /// # Constraints
        ///
        /// - $0 \leq a < n$
        /// - $0 \leq b < n$
        ///
        /// # Panics
        ///
        /// Panics if the above constraint is not satisfied.
        ///
        /// # Complexity
        ///
        /// - $O(\alpha(n))$ amortized
        pub fn same(&mut self, a: usize, b: usize) -> bool {
            assert!(a < self.n);
            assert!(b < self.n);
            self.leader(a) == self.leader(b)
        }

        /// Performs the Fɪɴᴅ operation.
        ///
        /// # Constraints
        ///
        /// - $0 \leq a < n$
        ///
        /// # Panics
        ///
        /// Panics if the above constraint is not satisfied.
        ///
        /// # Complexity
        ///
        /// - $O(\alpha(n))$ amortized
        pub fn leader(&mut self, a: usize) -> usize {
            assert!(a < self.n);
            if self.parent_or_size[a] < 0 {
                return a;
            }
            self.parent_or_size[a] = self.leader(self.parent_or_size[a] as usize) as i32;
            self.parent_or_size[a] as usize
        }

        /// Returns the size of the connected component that contains the vertex $a$.
        ///
        /// # Constraints
        ///
        /// - $0 \leq a < n$
        ///
        /// # Panics
        ///
        /// Panics if the above constraint is not satisfied.
        ///
        /// # Complexity
        ///
        /// - $O(\alpha(n))$ amortized
        pub fn size(&mut self, a: usize) -> usize {
            assert!(a < self.n);
            let x = self.leader(a);
            -self.parent_or_size[x] as usize
        }

        /// Divides the graph into connected components.
        ///
        /// The result may not be ordered.
        ///
        /// # Complexity
        ///
        /// - $O(n)$
        pub fn groups(&mut self) -> Vec<Vec<usize>> {
            let leader_buf = (0..self.n).map(|i| self.leader(i)).collect::<Vec<_>>();
            let mut group_size = vec![0usize; self.n];
            for &leader in leader_buf.iter() {
                group_size[leader] += 1;
            }
            let mut packed_count = 0usize;
            let mut packed = group_size
                .iter()
                .map(|&size| {
                    let val = packed_count;
                    packed_count += size;
                    (val, val)
                })
                .collect::<Vec<_>>();
            let mut result = vec![0usize; self.n];
            for (i, &leader) in leader_buf.iter().enumerate() {
                if let Some(range) = packed.get_mut(leader) {
                    result[range.1] = i;
                    range.1 += 1;
                }
            }
            packed
                .iter()
                .filter_map(|&(i, j)| {
                    if i != j {
                        Some(result[i..j].to_vec())
                    } else {
                        None
                    }
                })
                .collect::<Vec<_>>()
        }
    }

    #[cfg(test)]
    mod tests {
        use super::*;

        #[test]
        fn dsu_works() {
            let mut d = Dsu::new(4);
            d.merge(0, 1);
            assert!(d.same(0, 1));
            d.merge(1, 2);
            assert!(d.same(0, 2));
            assert_eq!(d.size(0), 3);
            assert!(!d.same(0, 3));
            assert_eq!(d.groups(), vec![vec![0, 1, 2], vec![3]]);
        }
    }
}
use dsu::*;

Submission Info

Submission Time
Task C - Path Graph?
User mizarjp
Language Rust (1.42.0)
Score 300
Code Size 41726 Byte
Status AC
Exec Time 18 ms
Memory 2948 KiB

Judge Result

Set Name Sample All AfterContest
Score / Max Score 0 / 0 300 / 300 0 / 0
Status
AC × 3
AC × 36
AC × 4
Set Name Test Cases
Sample 00_example_00.txt, 00_example_01.txt, 00_example_02.txt
All 00_example_00.txt, 00_example_01.txt, 00_example_02.txt, 01_dense_00.txt, 02_path_00.txt, 02_path_01.txt, 02_path_02.txt, 02_path_03.txt, 02_path_04.txt, 02_path_05.txt, 02_path_06.txt, 02_path_07.txt, 02_path_08.txt, 02_path_09.txt, 03_paths_00.txt, 03_paths_01.txt, 03_paths_02.txt, 04_cycles_00.txt, 04_cycles_01.txt, 04_cycles_02.txt, 04_cycles_03.txt, 04_cycles_04.txt, 04_cycles_05.txt, 05_corner_00.txt, 05_corner_01.txt, 05_corner_02.txt, 05_corner_03.txt, 05_corner_04.txt, 05_corner_05.txt, 06_random_00.txt, 06_random_01.txt, 06_random_02.txt, 06_random_03.txt, 06_random_04.txt, 07_small_00.txt, 07_small_01.txt
AfterContest 08_after_contest_00.txt, 08_after_contest_01.txt, 08_after_contest_02.txt, 08_after_contest_03.txt
Case Name Status Exec Time Memory
00_example_00.txt AC 7 ms 1984 KiB
00_example_01.txt AC 1 ms 1916 KiB
00_example_02.txt AC 1 ms 1984 KiB
01_dense_00.txt AC 1 ms 1956 KiB
02_path_00.txt AC 17 ms 2884 KiB
02_path_01.txt AC 17 ms 2948 KiB
02_path_02.txt AC 13 ms 2028 KiB
02_path_03.txt AC 14 ms 2584 KiB
02_path_04.txt AC 7 ms 2448 KiB
02_path_05.txt AC 15 ms 2768 KiB
02_path_06.txt AC 6 ms 2188 KiB
02_path_07.txt AC 16 ms 2732 KiB
02_path_08.txt AC 7 ms 2020 KiB
02_path_09.txt AC 2 ms 1928 KiB
03_paths_00.txt AC 2 ms 1956 KiB
03_paths_01.txt AC 1 ms 2016 KiB
03_paths_02.txt AC 1 ms 1968 KiB
04_cycles_00.txt AC 1 ms 1848 KiB
04_cycles_01.txt AC 1 ms 1852 KiB
04_cycles_02.txt AC 2 ms 2032 KiB
04_cycles_03.txt AC 1 ms 1972 KiB
04_cycles_04.txt AC 1 ms 2020 KiB
04_cycles_05.txt AC 1 ms 1968 KiB
05_corner_00.txt AC 16 ms 2820 KiB
05_corner_01.txt AC 18 ms 2824 KiB
05_corner_02.txt AC 14 ms 2936 KiB
05_corner_03.txt AC 16 ms 2888 KiB
05_corner_04.txt AC 14 ms 2892 KiB
05_corner_05.txt AC 15 ms 2904 KiB
06_random_00.txt AC 1 ms 2064 KiB
06_random_01.txt AC 2 ms 1844 KiB
06_random_02.txt AC 1 ms 1972 KiB
06_random_03.txt AC 1 ms 1968 KiB
06_random_04.txt AC 2 ms 1964 KiB
07_small_00.txt AC 1 ms 2068 KiB
07_small_01.txt AC 1 ms 1972 KiB
08_after_contest_00.txt AC 2 ms 2828 KiB
08_after_contest_01.txt AC 1 ms 2788 KiB
08_after_contest_02.txt AC 1 ms 2004 KiB
08_after_contest_03.txt AC 1 ms 1968 KiB