1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

グラフのトレイル 2

1
Posted at

今回は paiza の「グラフのトレイル 2」の問題に挑戦!

🧩 問題概要

🔽 与えられるもの
・頂点数 n の無向グラフ(1〜n)
・始点 s
・移動回数 k
・各頂点の隣接リスト

🔽 グラフの特徴
・無向グラフ
・自己ループなし
・多重辺なし

🔽 やること
・頂点 s からスタート
・ちょうど k 回移動する経路をすべて求める

🔽 トレイルの定義(超重要)
・同じ辺は2回使えない(←最重要)
・頂点は何回通ってもOK

🔽 出力
・1行目:トレイルの総数
・2行目以降:各経路(頂点の列)
 → 長さは k+1 個(始点含む)



入力例:

4 2 4 
1
2
3
1 3 4
2
2 4
2
2 3

出力例:

2
2 3 4 2 1
2 4 3 2 1






✅OK例:

const rl = require('readline').createInterface({ input: process.stdin });

const lines = [];
rl.on('line', line => lines.push(line));

rl.on('close', () => {
   const [n, s, k] = lines[0].split(' ').map(Number);
   
   const graph = [['dummy']];
   let idx = 1;
   for (let i = 0; i < n; i++) {
       const v = Number(lines[idx++]);
       graph.push(lines[idx++].split(' ').map(Number));
   }
   
   const visit = Array.from({ length: n+1}, () => []); // 訪問済みリスト(隣接リスト)
   const trails = [];
   
   function dfs(v, trail, edges, k) { // v = 現在地(現在の頂点)、trail = トレイルで訪れる頂点を順に並べた配列、edges = 通過済みの枝の配列、k = 残りの移動回数
       if (k === 0) {
           trails.push([...trail]); // コピーして保存
       } else {
           for (const next of graph[v]) {
               if (!edges[v][next]) {
                   edges[v][next] = true;
                   edges[next][v] = true;
                   
                   trail.push(next);
                   
                   dfs(next, trail, edges, k-1);
                   
                   edges[v][next] = false;
                   edges[next][v] = false;
                   
                   trail.pop();
               }
           }
       }
   }
   
   dfs(s, [s], visit, k);
   console.log(trails.length);
   trails.forEach(t => console.log(t.join(' ')));
});

🔍コードの流れ

🔽 全体の流れ
・入力を読み取る(n, s, k とグラフ構造)
・隣接リスト graph を作る
・「使った辺」を記録する配列 visit を用意
・結果を入れる trails を用意
・DFSをスタート(始点 s から)

🔽 DFSの流れ
・今いる頂点 v からスタート
・残り移動回数 k を見ながら探索

🔽 終了条件
・k が 0 になったら
 → 今までの経路(trail)をコピーして保存

🔽 探索処理
・今の頂点 v に隣接する頂点 next を1つずつ見る
・まだ使っていない辺(v → next)だけ使う

🔽 次の頂点へ進むとき
・その辺を「使用済み」にする(両方向)
・trail に next を追加
・次の頂点へ再帰(k を1減らす)

🔽 戻るとき(バックトラッキング)
・使った辺を「未使用」に戻す
・trail から最後の頂点を削除

🔽 最後
・すべての経路を探索し終えたら
・経路の数を出力
・各経路を1行ずつ出力






📝まとめ

🔽DFSの典型パターン
・「全列挙」→ DFSで探索
・条件を満たす経路だけ記録

🔽一番重要な考え方
・今回は「頂点」じゃなくて
👉 「辺」を使ったか管理する

🔽状態管理
・edges[a][b] で辺の使用状況を管理
・無向グラフなので
 → a→b と b→a を両方管理

🔽バックトラッキング
・進むとき → 使用済みにする
・戻るとき → 未使用に戻す

👉 これで「全パターン探索」ができる

🔽配列の扱い(超重要)
・そのまま保存 → 参照でバグる
・コピーして保存 → 正しい結果

🔽この問題のまとめ
👉「辺の再利用を禁止したDFS全列挙」

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?