結果
| 問題 |
No.2337 Equidistant
|
| コンテスト | |
| ユーザー |
FromBooska
|
| 提出日時 | 2023-06-03 11:14:46 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 1,980 ms / 4,000 ms |
| コード長 | 4,246 bytes |
| コンパイル時間 | 438 ms |
| コンパイル使用メモリ | 82,500 KB |
| 実行使用メモリ | 172,660 KB |
| 最終ジャッジ日時 | 2024-12-29 02:41:27 |
| 合計ジャッジ時間 | 30,749 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 28 |
ソースコード
# 僕の持ってるLCAクラスではできないことをACの人はやっているのでそのLCAクラスをコピペさせてもらう
# https://yukicoder.me/submissions/877289
# 部分木、子の数をdfsでやるとMLE or TLEなので、この方のqueにした
N, Q = map(int, input().split())
edges = [[] for i in range(N+1)]
for i in range(N-1):
a, b = map(int, input().split())
edges[a].append(b)
edges[b].append(a)
## library of LCA by class
## index start from 0
import sys
sys.setrecursionlimit(10**7)
from collections import deque
class LCA:
def __init__(self,n):
self.size = n
self.bitlen = n.bit_length()
self.ancestor = [[0]*self.size for i in range(self.bitlen)]
self.depth = [-1]*self.size
self.dis = [-1]*self.size
## using [log_n][n] [n][log_n]
## [log_n][n] is tend to faster than [n][log_n]
## get parent by bfs is probably faster than dfs
def make(self,root):
self.depth[root] = 0
self.dis[root] = 0
q = deque([root])
while q:
now = q.popleft()
for nex in edges[now]:
if self.depth[nex]>= 0:
continue
self.depth[nex] = self.depth[now]+1
self.dis[nex] = self.dis[now]+1
self.ancestor[0][nex] = now
q.append(nex)
for i in range(1,self.bitlen):
for j in range(self.size):
if self.ancestor[i-1][j] > 0:
self.ancestor[i][j] = self.ancestor[i-1][self.ancestor[i-1][j]]
def lca(self,x,y):
dx = self.depth[x]
dy = self.depth[y]
if dx < dy:
x,y = y,x
dx,dy = dy,dx
dif = dx-dy
while dif:
s = dif & (-dif)
x = self.ancestor[s.bit_length()-1][x]
dif -= s
while x != y:
j = 0
while self.ancestor[j][x] != self.ancestor[j][y]:
j += 1
if j == 0:
return self.ancestor[0][x]
x = self.ancestor[j-1][x]
y = self.ancestor[j-1][y]
return x
def par(self,x,dep): #親parent
now = x
for i in range(self.bitlen)[::-1]:
if 1 << i <= dep:
now = self.ancestor[i][now]
dep -= 1<<i
return now
# 部分木、子の数を数える
# dfsだとMLE, python3だとTLE
# なのでこの方のque方法にする
root = 1
child = [0]*(N+1)
visited = [0]*(N+1)
que = [root]
visited[root] = 1
topological = []
parent = [-1]*(N+1)
while que:
current = que.pop()
topological.append(current)
for nxt in edges[current]:
if visited[nxt] == 0:
parent[nxt] = current
visited[nxt] = 1
que.append(nxt)
for current in topological[::-1]:
count = 1
for nxt in edges[current]:
if nxt != parent[current]:
count += child[nxt]
child[current] = count
#print(child)
# もらったLCAクラスを使ってみる
lca = LCA(N+1) # 頂点数
lca.make(1) # ルート
for q in range(Q):
s, t = map(int, input().split())
if lca.depth[s] < lca.depth[t]:
s, t = t, s
# sの方を深い方にする
# 同じ深さならそのまま
p = lca.lca(s, t) # LCA, lowest common ancestor
distance_st = lca.depth[s] + lca.depth[t] - lca.depth[p]*2
if distance_st%2 == 1:
print(0)
continue
center = lca.par(s, distance_st//2)
# 深い方の頂点であるsから、距離の半分だけ木を登った点がcenter
#print('center', center)
if lca.depth[s] != lca.depth[t]:
ans = child[center] - child[lca.par(s, distance_st//2-1)]
# s, t の深さが違うときは
# centerの子の数から、深い方sからcenterの一歩手前の頂点の子の数を引く
else:
#ans = N - child[lca.par(s, distance_st//2-1)] - child[lca.par(t,distance_st//2-1)]
ans = N - child[lca.par(s, distance_st//2-1)] - child[lca.par(t, distance_st//2-1)]
# s, tの深さが同じ時は
# Nから
# centerの一歩手前の頂点の子の数を引く、両方分
print(ans)
FromBooska