Skip to content

Commit

Permalink
Add yukicoder/1502.rs yukicoder/1572.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
koba-e964 committed Aug 29, 2023
1 parent 88ad829 commit 2fccdf0
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 0 deletions.
113 changes: 113 additions & 0 deletions yukicoder/1502.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
use std::cmp::*;
// https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
macro_rules! input {
($($r:tt)*) => {
let stdin = std::io::stdin();
let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
let mut next = move || -> String{
bytes.by_ref().map(|r|r.unwrap() as char)
.skip_while(|c|c.is_whitespace())
.take_while(|c|!c.is_whitespace())
.collect()
};
input_inner!{next, $($r)*}
};
}

macro_rules! input_inner {
($next:expr) => {};
($next:expr,) => {};
($next:expr, $var:ident : $t:tt $($r:tt)*) => {
let $var = read_value!($next, $t);
input_inner!{$next $($r)*}
};
}

macro_rules! read_value {
($next:expr, ( $($t:tt),* )) => { ($(read_value!($next, $t)),*) };
($next:expr, [ $t:tt ; $len:expr ]) => {
(0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
};
($next:expr, usize1) => (read_value!($next, usize) - 1);
($next:expr, $t:ty) => ($next().parse::<$t>().expect("Parse error"));
}

fn main() {
// In order to avoid potential stack overflow, spawn a new thread.
let stack_size = 104_857_600; // 100 MB
let thd = std::thread::Builder::new().stack_size(stack_size);
thd.spawn(|| solve()).unwrap().join().unwrap();
}

const MOD: i64 = 1_000_000_007;

fn dfs(
v: usize, g: &[Vec<(usize, i64)>], k: i64,
vis: &mut [bool], eq: &mut Vec<i64>, pot: &mut [(i64, i64)],
p: (i64, i64),
) -> (i64, i64) {
let (mut lo, mut hi) = if p.0 == 1 {
(1 - p.1, k - p.1)
} else {
(p.1 - k, p.1 - 1)
};
if vis[v] {
if pot[v].0 == p.0 {
return if pot[v].1 == p.1 {
(lo, hi)
} else {
(1, 0) // contradiction
};
}
eq.push((p.1 - pot[v].1) * 2 / (pot[v].0 - p.0));
return (lo, hi);
}
vis[v] = true;
pot[v] = p;
for &(w, c) in &g[v] {
let (sublo, subhi) = dfs(w, g, k, vis, eq, pot, (-p.0, c - p.1));
lo = max(lo, sublo);
hi = min(hi, subhi);
}
(lo, hi)
}

fn calc(n: usize, xyz: &[(usize, usize, i64)], k: i64) -> i64 {
let mut g = vec![vec![]; n];
for &(x, y, z) in xyz {
g[x].push((y, z));
g[y].push((x, z));
}
let mut vis = vec![false; n];
let mut ans = 1;
let mut pot = vec![(0, 0); n];
for i in 0..n {
let mut eq = vec![];
if !vis[i] {
let (mi, ma) = dfs(i, &g, k, &mut vis, &mut eq, &mut pot, (1, 0));
eq.dedup();
if mi > ma || eq.len() >= 2 {
return 0;
}
if eq.len() == 1 {
let x = eq[0];
if x % 2 != 0 || mi > x / 2 || x / 2 > ma {
return 0;
}
} else {
ans = ans * (ma - mi + 1) % MOD;
}
}
}
ans
}

// https://yukicoder.me/problems/no/1502 (3.5)
// <= k に変換すれば DFS で制約を見つけるだけになる。
fn solve() {
input! {
n: usize, m: usize, k: i64,
xyz: [(usize1, usize1, i64); m],
}
println!("{}", (calc(n, &xyz, k) - calc(n, &xyz, k - 1) + MOD) % MOD);
}
78 changes: 78 additions & 0 deletions yukicoder/1572.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use std::collections::*;
// https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
macro_rules! input {
($($r:tt)*) => {
let stdin = std::io::stdin();
let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
let mut next = move || -> String{
bytes.by_ref().map(|r|r.unwrap() as char)
.skip_while(|c|c.is_whitespace())
.take_while(|c|!c.is_whitespace())
.collect()
};
input_inner!{next, $($r)*}
};
}

macro_rules! input_inner {
($next:expr) => {};
($next:expr,) => {};
($next:expr, $var:ident : $t:tt $($r:tt)*) => {
let $var = read_value!($next, $t);
input_inner!{$next $($r)*}
};
}

macro_rules! read_value {
($next:expr, [ $t:tt ; $len:expr ]) => {
(0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
};
($next:expr, chars) => {
read_value!($next, String).chars().collect::<Vec<char>>()
};
($next:expr, usize1) => (read_value!($next, usize) - 1);
($next:expr, $t:ty) => ($next().parse::<$t>().expect("Parse error"));
}

// https://yukicoder.me/problems/no/1572 (3)
// (位置, 1 の向き) という状態それぞれに対して頂点を作って BFS。
fn main() {
input! {
h: usize, w: usize,
sx: usize1, sy: usize1,
gx: usize1, gy: usize1,
a: [chars; h],
}
const INF: i64 = 1 << 28;
let mut dist = vec![vec![[INF; 6]; w]; h];
let mut que = VecDeque::new();
que.push_back((0, sx, sy, 4));
let dxy = [(0i32, 1i32), (-1, 0), (0, -1), (1, 0)];
while let Some((d, x, y, z)) = que.pop_front() {
if dist[x][y][z] <= d { continue; }
dist[x][y][z] = d;
for i in 0..4 {
let nz = if z == 4 {
i
} else if z == 5 {
(i + 2) % 4
} else if z == i {
5
} else if z == (i + 2) % 4 {
4
} else {
z
};
let (dx, dy) = dxy[i];
let nx = (x as i32 + dx) as usize;
let ny = (y as i32 + dy) as usize;
if nx >= h || ny >= w {
continue;
}
if a[nx][ny] == '#' { continue; }
que.push_back((d + 1, nx, ny, nz));
}
}
let ans = dist[gx][gy][4];
println!("{}", if ans >= INF { -1 } else { ans });
}

0 comments on commit 2fccdf0

Please sign in to comment.