【AtCoder】ABC 448 D - Integer-duplicated Path
AtCoder/ABC/D問題AtCoder/ABC/400点問題AtCoder/茶DiffAtCoder/NoviSteps/1QAtCoder/グラフ問題/木AtCoder/DFS競技プログラミング

D - Integer-duplicated Path
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
AtCoder
実行時間制限: 2 sec / メモリ制限: 1024 MiB / Difficulty: 638 / NoviSteps: 1Q / 配点: 400 点
問題概要
頂点 の 頂点からなる木が与えられ、この木の辺のうち 本目は頂点 と頂点 を結んでいる。 頂点 には整数 が書かれている。
全ての について以下の問題に答えよ。
- 頂点 から頂点 への単純パスに含まれる頂点について、同じ整数の書かれた異なる 頂点の組が存在すれば
Yes、そうでないならNoと答えよ。- なお、木上の つの頂点を結ぶ単純なパスが一意に定まることは証明できる。
制約
- 入力は全て整数
考察
与えられるグラフは木なので、頂点 を根とすれば任意の頂点 までの単純パスは一意に定まり、DFS を用いて全ての頂点に対する根からのパスを計算することができる。
DFS で根からある頂点 に到達したとき、ここまでのパス上に同じ整数の書かれた異なる 頂点の組が存在するかどうかを判定するのだが、愚直に行うと の計算量となってしまう。
これを高速化するために、「現在のパス上にどの整数が何個あるか」を記録する連想配列と、「重複している整数の種類数」を記録するカウンターを保持することを考える。 その上で、以下のような操作を行う。
- ある頂点に到達したとき(行きがけ)
- その頂点の整数を、連想配列に追加する。もし追加する前にすでにその整数の個数が 個あればカウンターを 増やす。
- ある頂点からその親の頂点に戻るとき(帰りがけ)
- その頂点の整数を、連想配列から減らす。もし減らす前にその整数の個数が 個あればカウンターを 減らす。
これにより、頂点に到達した時点でカウンターが より大きいかどうかをチェックするだけで、判定処理を の計算量で行うことができる。
したがって、全体としては DFS を行うだけとなり、計算量は である。
実装例
CPP
1.#include <bits/stdc++.h>2.using namespace std;3. 4.#define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++)5. 6.template <class T>7.using Graph = vector<vector<T>>;8. 9.// ======================================== //10. 11.int main()12.{13. int N;14. cin >> N;15. vector<int> A(N);16. rep(i, 0, N) cin >> A[i];17. Graph<int> G(N);18. rep(i, 0, N - 1)19. {20. int U, V;21. cin >> U >> V;22. U--, V--;23. G[U].push_back(V);24. G[V].push_back(U);25. }26. 27. map<int, int> mp;28. vector<bool> ans(N, false);29. int cnt = 0;30. 31. auto dfs = [&](auto self, int now, int parent) -> void32. {33. if (mp[A[now]] == 1)34. cnt++;35. mp[A[now]]++;36. 37. if (cnt > 0)38. ans[now] = true;39. else40. ans[now] = false;41. 42. for (auto &&next : G[now])43. {44. if (next == parent)45. continue;46. self(self, next, now);47. }48. 49. mp[A[now]]--;50. if (mp[A[now]] == 1)51. cnt--;52. };53. 54. dfs(dfs, 0, -1);55. 56. rep(i, 0, N)57. {58. if (ans[i])59. cout << "Yes" << endl;60. else61. cout << "No" << endl;62. }63. 64. return 0;65.}
Submission #73885158 - AtCoder Beginner Contest 448
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
AtCoder
実装時間: 20 分
コメント
これは DFS のいい練習になる問題だった。





