結果
| 問題 |
No.2337 Equidistant
|
| コンテスト | |
| ユーザー |
yupooh
|
| 提出日時 | 2023-06-02 22:08:27 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 4,003 bytes |
| コンパイル時間 | 1,029 ms |
| コンパイル使用メモリ | 82,176 KB |
| 実行使用メモリ | 497,176 KB |
| 最終ジャッジ日時 | 2024-12-28 18:20:50 |
| 合計ジャッジ時間 | 19,225 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | WA * 28 |
ソースコード
import sys
input = sys.stdin.readline
sys.setrecursionlimit(500000)
n,q=map(int,input().split())
adj=[[] for _ in range(n)]
for _ in range(n-1):
a,b=map(int,input().split())
adj[a-1].append(b-1)
adj[b-1].append(a-1)
depth = [0]*n
seen = [0]*n
size=[0]*n
def dfs(v, e):
depth[v] = e
seen[v]=1
tot=1
for w in adj[v]:
if seen[w]==0:
tot+=dfs(w, e+1)
size[v]=tot
return tot
dfs(0, 0)
class HLD:
def __init__(self, g):
self.g = g
self.n = len(g)
self.parent = [-1]*self.n
self.size = [1]*self.n
self.head = [0]*self.n
self.preorder = [0]*self.n
self.k = 0
for v in range(self.n):
if self.parent[v] == -1:
self.dfs_pre(v)
self.dfs_hld(v)
def dfs_pre(self, v):
g = self.g
stack = [v]
order = [v]
while stack:
v = stack.pop()
for u in g[v]:
if self.parent[v] == u:
continue
self.parent[u] = v
stack.append(u)
order.append(u)
# 隣接リストの左端: heavyな頂点への辺
# 隣接リストの右端: 親への辺
while order:
v = order.pop()
child_v = g[v]
if len(child_v) and child_v[0] == self.parent[v]:
child_v[0], child_v[-1] = child_v[-1], child_v[0]
for i, u in enumerate(child_v):
if u == self.parent[v]:
continue
self.size[v] += self.size[u]
if self.size[u] > self.size[child_v[0]]:
child_v[i], child_v[0] = child_v[0], child_v[i]
def dfs_hld(self, v):
stack = [v]
while stack:
v = stack.pop()
self.preorder[v] = self.k
self.k += 1
top = self.g[v][0]
# 隣接リストを逆順に見ていく(親 > lightな頂点への辺 > heavyな頂点 (top))
# 連結成分が連続するようにならべる
for u in reversed(self.g[v]):
if u == self.parent[v]:
continue
if u == top:
self.head[u] = self.head[v]
else:
self.head[u] = u
stack.append(u)
def for_each(self, u, v):
# [u, v]上の頂点集合の区間を列挙
while True:
if self.preorder[u] > self.preorder[v]:
u, v = v, u
l = max(self.preorder[self.head[v]], self.preorder[u])
r = self.preorder[v]
yield l, r # [l, r]
if self.head[u] != self.head[v]:
v = self.parent[self.head[v]]
else:
return
def for_each_edge(self, u, v):
# [u, v]上の辺集合の区間列挙
# 辺の情報は子の頂点に
while True:
if self.preorder[u] > self.preorder[v]:
u, v = v, u
if self.head[u] != self.head[v]:
yield self.preorder[self.head[v]], self.preorder[v]
v = self.parent[self.head[v]]
else:
if u != v:
yield self.preorder[u]+1, self.preorder[v]
break
def subtree(self, v):
# 頂点vの部分木の頂点集合の区間 [l, r)
l = self.preorder[v]
r = self.preorder[v]+self.size[v]
return l, r
def lca(self, u, v):
# 頂点u, vのLCA
while True:
if self.preorder[u] > self.preorder[v]:
u, v = v, u
if self.head[u] == self.head[v]:
return u
v = self.parent[self.head[v]]
hld = HLD(adj)
for _ in range(q):
s,t=map(int,input().split())
s-=1
t-=1
x=hld.lca(s,t)
d=depth[s]+depth[t]-2*depth[x]
if d%2==1:
print(0)
continue
if depth[s]-depth[x]==d//2:
print(n-size[x]+1)
else:
print(size[x])
yupooh