Hopscotch Addict

グラフの構築

ABC132-E Hopscotch Addict

概要

有向グラフG(N, M)が与えられ, グラフ上を一度の移動で3頂点進む. 頂点Sから頂点Tまで移動できる場合の最短経路を求める.

2N105,0Mmin(105,N(N1))2 \leq N \leq 10^5, 0 \leq M \leq min(10^5, N(N-1))

考察

頂点Sから頂点Tの経路かつ経路長が3の倍数であるもののうち, 最短のものを求めたい. 長さが3の倍数であるという制約を扱うために, 以下のようにグラフに遷移状態をもたせる.

A
B
C
D
A, 0
B, 1
C, 2
D, 0

このようにすることで(A, 0) => (D, 0)のパスの長さが3となる.
ここでD → Aのパスがあると仮定すると, 二週目は以下のようになる.

D, 0
A, 1
B, 2
C, 0

よって(A, 0) => (D, 0) => (C, 0)のパスが制約のもとで存在することがわかる.
このようにして(S, 0) => (T, 0) のパスが存在するかどうかを判定すればよい.

解答

遷移した回数をvとして, 0, 1, 2, 0, 1, ...の状態は v % 3で管理した.

use std::io;
use std::collections::VecDeque;

/// head comment
fn main() {
    let (n, m) = {
        let i = read::<usize>();
        (i[0], i[1])
    };

    // line comment
    let mut g = vec![Vec::new(); n];
    for _ in 0..m {
        let (u, v) = {
            let i = read::<usize>();
            (i[0] - 1, i[1] - 1)
        };
        g[u].push(v);
    }
    let (s, t) = {
        let i = read::<usize>();
        (i[0] - 1, i[1] - 1)
    };

    let mut que = VecDeque::new();
    let mut dist = vec![vec![::std::usize::MAX; 3]; n];
    que.push_back((s, 0));
    while let Some((u, v)) = que.pop_front() {
        if dist[u][v % 3] != ::std::usize::MAX { continue; }
        dist[u][v % 3] = v;

        for i in 0..g[u].len() {
            let vv = g[u][i];
            que.push_back((vv, v + 1));
        }
    }

    if dist[t][0] != ::std::usize::MAX { println!("{}", dist[t][0] / 3); }
    else { println!("-1"); }
}

Commits

2021-10-14 18:03:326ea7adc9add graph & styling
commit 6ea7adc9d04f6d7a20a65ddc13452e154e8d4ecb
Author: koka &&gt;
Date:   Thu Oct 14 18:03:32 2021 +0900

  add graph & styling

diff --git a/_posts/2019-11-18-abc132-e.md b/_posts/2019-11-18-abc132-e.md
index 24e3449..83fd070 100644
--- a/_posts/2019-11-18-abc132-e.md
+++ b/_posts/2019-11-18-abc132-e.md
@@ -20,39 +20,43 @@ $$2 \leq N \leq 10^5, 0 \leq M \leq min(10^5, N(N-1))$$
頂点Sから頂点Tの経路かつ経路長が3の倍数であるもののうち, 最短のものを求めたい.
長さが3の倍数であるという制約を扱うために, 以下のようにグラフに遷移状態をもたせる.

-\```html
-&lt;div class="graph"&gt;
-  &lt;div class="edge"&gt;A&lt;/div&gt;
-    &lt;div class="node" /&gt;
-  &lt;div class="edge"&gt;B&lt;/div&gt;
-    &lt;div class="node" /&gt;
-  &lt;div class="edge"&gt;C&lt;/div&gt;
-    &lt;div class="node" /&gt;
-  &lt;div class="edge"&gt;D&lt;/div&gt;
+&lt;div class="graph-wrapper"&gt;
+  &lt;div class="graph"&gt;
+    &lt;div class="edge"&gt;A&lt;/div&gt;
+    &lt;div class="node"&gt;&lt;/div&gt;
+    &lt;div class="edge"&gt;B&lt;/div&gt;
+    &lt;div class="node"&gt;&lt;/div&gt;
+    &lt;div class="edge"&gt;C&lt;/div&gt;
+    &lt;div class="node"&gt;&lt;/div&gt;
+    &lt;div class="edge"&gt;D&lt;/div&gt;
+  &lt;/div&gt;
&lt;/div&gt;

-&lt;div class="graph"&gt;
-  &lt;div class="edge"&gt;A, 0&lt;/div&gt;
-    &lt;div class="node" /&gt;
-  &lt;div class="edge"&gt;B, 1&lt;/div&gt;
-    &lt;div class="node" /&gt;
-  &lt;div class="edge"&gt;C, 2&lt;/div&gt;
-    &lt;div class="node" /&gt;
-  &lt;div class="edge"&gt;D, 0&lt;/div&gt;
+&lt;div&gt;
+  &lt;div class="graph"&gt;
+    &lt;div class="edge"&gt;A, 0&lt;/div&gt;
+    &lt;div class="node"&gt;&lt;/div&gt;
+    &lt;div class="edge"&gt;B, 1&lt;/div&gt;
+    &lt;div class="node"&gt;&lt;/div&gt;
+    &lt;div class="edge"&gt;C, 2&lt;/div&gt;
+    &lt;div class="node"&gt;&lt;/div&gt;
+    &lt;div class="edge"&gt;D, 0&lt;/div&gt;
+  &lt;/div&gt;
&lt;/div&gt;
-\```

このようにすることで`(A, 0) =&gt; (D, 0)`のパスの長さが3となる.  
ここで`D → A`のパスがあると仮定すると, 二週目は以下のようになる.

-&lt;div class="graph"&gt;
-  &lt;div class="edge"&gt;D, 0&lt;/div&gt;
-    &lt;div class="node" /&gt;
-  &lt;div class="edge"&gt;A, 1&lt;/div&gt;
-    &lt;div class="node" /&gt;
-  &lt;div class="edge"&gt;B, 2&lt;/div&gt;
-    &lt;div class="node" /&gt;
-  &lt;div class="edge"&gt;C, 0&lt;/div&gt;
+&lt;div class="graph-wrapper"&gt;
+  &lt;div class="graph"&gt;
+    &lt;div class="edge"&gt;D, 0&lt;/div&gt;
+    &lt;div class="node"&gt;&lt;/div&gt;
+    &lt;div class="edge"&gt;A, 1&lt;/div&gt;
+    &lt;div class="node"&gt;&lt;/div&gt;
+    &lt;div class="edge"&gt;B, 2&lt;/div&gt;
+    &lt;div class="node"&gt;&lt;/div&gt;
+    &lt;div class="edge"&gt;C, 0&lt;/div&gt;
+  &lt;/div&gt;
&lt;/div&gt;

よって`(A, 0) =&gt; (D, 0) =&gt; (C, 0)`のパスが制約のもとで存在することがわかる.  
@@ -103,3 +107,37 @@ fn main() {
   else { println!("-1"); }
}
\```
+
+&lt;style&gt;
+.graph-wrapper {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: space-around;
+}
+
+.graph {
+  margin: 2rem 0;
+  font-size: 0.8rem;
+  display: flex;
+  justify-content: center;
+}
+
+.graph .edge {
+  position: relative;
+  z-index: 0;
+  background: #98971a;
+  width: 2.5rem;
+  height: 2.5rem;
+  border-radius: 50%;
+  text-align: center;
+  line-height: 2.5rem;
+}
+
+.graph .node {
+  position: relative;
+  width: 2rem;
+  height: 1.2rem;
+  border-bottom: 1.5px solid #7c6f64;
+  text-align: center;
+}
+&lt;/style&gt;
2021-03-05 18:48:4170a0aff5wip
commit 70a0aff5a83d4332a8c3ccff3d2d3c1c84e46ef2
Author: koka &&gt;
Date:   Fri Mar 5 18:48:41 2021 +0900

  wip

diff --git a/_posts/2019-11-18-abc132-e.md b/_posts/2019-11-18-abc132-e.md
index 4a2e5c1..24e3449 100644
--- a/_posts/2019-11-18-abc132-e.md
+++ b/_posts/2019-11-18-abc132-e.md
@@ -14,12 +14,34 @@ description: グラフの構築
### 概要
有向グラフ`G(N, M)`が与えられ, グラフ上を一度の移動で3頂点進む. 頂点Sから頂点Tまで移動できる場合の最短経路を求める.

-$2 \leq N \leq 10^5, 0 \leq M \leq min(10^5, N(N-1))$
+$$2 \leq N \leq 10^5, 0 \leq M \leq min(10^5, N(N-1))$$

### 考察
頂点Sから頂点Tの経路かつ経路長が3の倍数であるもののうち, 最短のものを求めたい.
長さが3の倍数であるという制約を扱うために, 以下のようにグラフに遷移状態をもたせる.

+\```html
+&lt;div class="graph"&gt;
+  &lt;div class="edge"&gt;A&lt;/div&gt;
+    &lt;div class="node" /&gt;
+  &lt;div class="edge"&gt;B&lt;/div&gt;
+    &lt;div class="node" /&gt;
+  &lt;div class="edge"&gt;C&lt;/div&gt;
+    &lt;div class="node" /&gt;
+  &lt;div class="edge"&gt;D&lt;/div&gt;
+&lt;/div&gt;
+
+&lt;div class="graph"&gt;
+  &lt;div class="edge"&gt;A, 0&lt;/div&gt;
+    &lt;div class="node" /&gt;
+  &lt;div class="edge"&gt;B, 1&lt;/div&gt;
+    &lt;div class="node" /&gt;
+  &lt;div class="edge"&gt;C, 2&lt;/div&gt;
+    &lt;div class="node" /&gt;
+  &lt;div class="edge"&gt;D, 0&lt;/div&gt;
+&lt;/div&gt;
+\```
+
このようにすることで`(A, 0) =&gt; (D, 0)`のパスの長さが3となる.  
ここで`D → A`のパスがあると仮定すると, 二週目は以下のようになる.
2021-02-15 00:35:552716e36bremove old
commit 2716e36b1d32e442f2826e8a1946a44400ca8bdf
Author: koka &&gt;
Date:   Mon Feb 15 00:35:55 2021 +0900

  remove old

diff --git a/_posts/2019-11-18-abc132-e.md b/_posts/2019-11-18-abc132-e.md
index a107a9d..4a2e5c1 100644
--- a/_posts/2019-11-18-abc132-e.md
+++ b/_posts/2019-11-18-abc132-e.md
@@ -20,26 +20,6 @@ $2 \leq N \leq 10^5, 0 \leq M \leq min(10^5, N(N-1))$
頂点Sから頂点Tの経路かつ経路長が3の倍数であるもののうち, 最短のものを求めたい.
長さが3の倍数であるという制約を扱うために, 以下のようにグラフに遷移状態をもたせる.

-&lt;div class="graph"&gt;
-  &lt;div class="edge"&gt;A&lt;/div&gt;
-    &lt;div class="node" /&gt;
-  &lt;div class="edge"&gt;B&lt;/div&gt;
-    &lt;div class="node" /&gt;
-  &lt;div class="edge"&gt;C&lt;/div&gt;
-    &lt;div class="node" /&gt;
-  &lt;div class="edge"&gt;D&lt;/div&gt;
-&lt;/div&gt;
-
-&lt;div class="graph"&gt;
-  &lt;div class="edge"&gt;A, 0&lt;/div&gt;
-    &lt;div class="node" /&gt;
-  &lt;div class="edge"&gt;B, 1&lt;/div&gt;
-    &lt;div class="node" /&gt;
-  &lt;div class="edge"&gt;C, 2&lt;/div&gt;
-    &lt;div class="node" /&gt;
-  &lt;div class="edge"&gt;D, 0&lt;/div&gt;
-&lt;/div&gt;
-
このようにすることで`(A, 0) =&gt; (D, 0)`のパスの長さが3となる.  
ここで`D → A`のパスがあると仮定すると, 二週目は以下のようになる.
2021-02-15 00:34:10bd59f09aupdate
commit bd59f09a33181a1f762978251b6b4d7eb0095a09
Author: koka &&gt;
Date:   Mon Feb 15 00:34:10 2021 +0900

  update

diff --git a/_posts/2019-11-18-abc132-e.md b/_posts/2019-11-18-abc132-e.md
index d07b8a9..a107a9d 100644
--- a/_posts/2019-11-18-abc132-e.md
+++ b/_posts/2019-11-18-abc132-e.md
@@ -10,11 +10,11 @@ description: グラフの構築
---

## ABC132-E Hopscotch Addict
+
### 概要
有向グラフ`G(N, M)`が与えられ, グラフ上を一度の移動で3頂点進む. 頂点Sから頂点Tまで移動できる場合の最短経路を求める.

-$2 \leq N \leq 10^5$,
-$0 \leq M \leq min(10^5, N(N-1))$
+$2 \leq N \leq 10^5, 0 \leq M \leq min(10^5, N(N-1))$

### 考察
頂点Sから頂点Tの経路かつ経路長が3の倍数であるもののうち, 最短のものを求めたい.
@@ -59,15 +59,18 @@ $0 \leq M \leq min(10^5, N(N-1))$
### 解答
遷移した回数を`v`として, `0, 1, 2, 0, 1, ...`の状態は `v % 3`で管理した.

-\```rust
+\```rust[class="line-numbers"][data-file="e.rs"]
use std::io;
use std::collections::VecDeque;

+/// head comment
fn main() {
   let (n, m) = {
       let i = read::&lt;usize&gt;();
       (i[0], i[1])
   };
+
+    // line comment
   let mut g = vec![Vec::new(); n];
   for _ in 0..m {
       let (u, v) = {
2021-01-30 22:18:1735b550aecopy md
commit 35b550ae83af4efaeadf33471c8ca8a32c1079c8
Author: koka &&gt;
Date:   Sat Jan 30 22:18:17 2021 +0900

  copy md

diff --git a/_posts/2019-11-18-abc132-e.md b/_posts/2019-11-18-abc132-e.md
new file mode 100644
index 0000000..d07b8a9
--- /dev/null
+++ b/_posts/2019-11-18-abc132-e.md
@@ -0,0 +1,100 @@
+---
+title: 'Hopscotch Addict'
+date: 2019-11-18
+categories:
+- Competitive Programming
+tags:
+- AtCoder
+- Graph
+description: グラフの構築
+---
+
+## [ABC132-E Hopscotch Addict](https://atcoder.jp/contests/abc132/tasks/abc132_e)
+### 概要
+有向グラフ`G(N, M)`が与えられ, グラフ上を一度の移動で3頂点進む. 頂点Sから頂点Tまで移動できる場合の最短経路を求める.
+
+$2 \leq N \leq 10^5$,
+$0 \leq M \leq min(10^5, N(N-1))$
+
+### 考察
+頂点Sから頂点Tの経路かつ経路長が3の倍数であるもののうち, 最短のものを求めたい.
+長さが3の倍数であるという制約を扱うために, 以下のようにグラフに遷移状態をもたせる.
+
+&lt;div class="graph"&gt;
+  &lt;div class="edge"&gt;A&lt;/div&gt;
+    &lt;div class="node" /&gt;
+  &lt;div class="edge"&gt;B&lt;/div&gt;
+    &lt;div class="node" /&gt;
+  &lt;div class="edge"&gt;C&lt;/div&gt;
+    &lt;div class="node" /&gt;
+  &lt;div class="edge"&gt;D&lt;/div&gt;
+&lt;/div&gt;
+
+&lt;div class="graph"&gt;
+  &lt;div class="edge"&gt;A, 0&lt;/div&gt;
+    &lt;div class="node" /&gt;
+  &lt;div class="edge"&gt;B, 1&lt;/div&gt;
+    &lt;div class="node" /&gt;
+  &lt;div class="edge"&gt;C, 2&lt;/div&gt;
+    &lt;div class="node" /&gt;
+  &lt;div class="edge"&gt;D, 0&lt;/div&gt;
+&lt;/div&gt;
+
+このようにすることで`(A, 0) =&gt; (D, 0)`のパスの長さが3となる.  
+ここで`D → A`のパスがあると仮定すると, 二週目は以下のようになる.
+
+&lt;div class="graph"&gt;
+  &lt;div class="edge"&gt;D, 0&lt;/div&gt;
+    &lt;div class="node" /&gt;
+  &lt;div class="edge"&gt;A, 1&lt;/div&gt;
+    &lt;div class="node" /&gt;
+  &lt;div class="edge"&gt;B, 2&lt;/div&gt;
+    &lt;div class="node" /&gt;
+  &lt;div class="edge"&gt;C, 0&lt;/div&gt;
+&lt;/div&gt;
+
+よって`(A, 0) =&gt; (D, 0) =&gt; (C, 0)`のパスが制約のもとで存在することがわかる.  
+このようにして`(S, 0) =&gt; (T, 0)` のパスが存在するかどうかを判定すればよい.
+
+### 解答
+遷移した回数を`v`として, `0, 1, 2, 0, 1, ...`の状態は `v % 3`で管理した.
+
+\```rust
+use std::io;
+use std::collections::VecDeque;
+
+fn main() {
+    let (n, m) = {
+        let i = read::&lt;usize&gt;();
+        (i[0], i[1])
+    };
+    let mut g = vec![Vec::new(); n];
+    for _ in 0..m {
+        let (u, v) = {
+            let i = read::&lt;usize&gt;();
+            (i[0] - 1, i[1] - 1)
+        };
+        g[u].push(v);
+    }
+    let (s, t) = {
+        let i = read::&lt;usize&gt;();
+        (i[0] - 1, i[1] - 1)
+    };
+
+    let mut que = VecDeque::new();
+    let mut dist = vec![vec![::std::usize::MAX; 3]; n];
+    que.push_back((s, 0));
+    while let Some((u, v)) = que.pop_front() {
+        if dist[u][v % 3] != ::std::usize::MAX { continue; }
+        dist[u][v % 3] = v;
+
+        for i in 0..g[u].len() {
+            let vv = g[u][i];
+            que.push_back((vv, v + 1));
+        }
+    }
+
+    if dist[t][0] != ::std::usize::MAX { println!("{}", dist[t][0] / 3); }
+    else { println!("-1"); }
+}
+\```