D - Collision Editorial by blackyuki
これらの用語を初めて聞いたという方は、本解説を読む前にインターネットなどで検索することをお勧めします。
道路の長さを \(1\) として、街 \(1\) との最短距離が偶数であるような街を赤、そうでない街を青で塗ることにします。 すると、木の二部グラフ性により、赤の街にいた人は次青の街へ、逆に青の街にいた人は次赤の街へ移動するということが分かります。よって高橋君と青木君のスタート地点の色が異なっていれば、二人は必ず同じ街で出会うことはありません。逆に、高橋君と青木君のスタート地点の色が同じであれば、二人は必ず道路で出会うことはありません。 各街の色を求めるには幅優先探索や深さ優先探索を使うと良いです。必要な前提知識
解説
よって初めに各街の色を前計算しておくことで各クエリに \(O(1)\) で答えることができます。実装例 (C++)
#include<bits/stdc++.h>
using namespace std;
int main(){
int N, Q; cin >> N >> Q;
vector<vector<int>> G(N);
for(int i = 0; i < N-1; i++){
int A, B; cin >> A >> B;
G[A-1].push_back(B-1);
G[B-1].push_back(A-1);
}
queue<int> que;
vector<int> dis(N,-1);
que.push(0);
dis[0] = 0;
while(!que.empty()){
int t = que.front(); que.pop();
for(int x: G[t]) if(dis[x] == -1) {
dis[x] = dis[t] + 1;
que.push(x);
}
}
for(int i = 0; i < Q; i++){
int A, B;cin >> A >> B;
if(dis[A-1]%2 == dis[B-1]%2) cout << "Town" << endl;
if(dis[A-1]%2 != dis[B-1]%2) cout << "Road" << endl;
}
}
実装例 (Python)
import queue
N,Q=map(int,input().split())
G=[[] for i in range(N)]
for i in range(N-1):
a,b=map(int,input().split())
G[a-1].append(b-1)
G[b-1].append(a-1)
que=queue.Queue()
color=[-1]*N
color[0]=0
que.put(0)
while not que.empty():
t=que.get()
for i in G[t]:
if color[i] == -1:
color[i] = 1 - color[t]
que.put(i)
for i in range(Q):
a,b=map(int,input().split())
if color[a-1] == color[b-1]:
print("Town")
else:
print("Road")
posted:
last update: