結果
| 問題 | No.922 東北きりきざむたん |
| コンテスト | |
| ユーザー |
titia
|
| 提出日時 | 2025-12-29 03:38:24 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 894 ms / 2,000 ms |
| コード長 | 4,067 bytes |
| 記録 | |
| コンパイル時間 | 282 ms |
| コンパイル使用メモリ | 82,896 KB |
| 実行使用メモリ | 127,076 KB |
| 最終ジャッジ日時 | 2025-12-29 03:38:43 |
| 合計ジャッジ時間 | 16,308 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 26 |
ソースコード
import sys
input = sys.stdin.readline
from collections import deque
N,M,Q=map(int,input().split())
# UnionFind
Group = [i for i in range(N)] # グループ分け
Nodes = [1]*(N) # 各グループのノードの数
def find(x):
while Group[x] != x:
x=Group[x]
return x
def Union(x,y):
if find(x) != find(y):
if Nodes[find(x)] < Nodes[find(y)]:
Nodes[find(y)] += Nodes[find(x)]
Nodes[find(x)] = 0
Group[find(x)] = find(y)
else:
Nodes[find(x)] += Nodes[find(y)]
Nodes[find(y)] = 0
Group[find(y)] = find(x)
E=[[] for i in range(N)]
for i in range(M):
x,y=map(int,input().split())
x-=1
y-=1
E[x].append(y)
E[y].append(x)
Union(x,y)
A=[0]*N
QU=[[] for i in range(N)]
for i in range(Q):
x,y=map(int,input().split())
x-=1
y-=1
if find(x)==find(y):
QU[find(x)].append((x,y))
else:
A[x]+=1
A[y]+=1
F=[[] for i in range(N)]
for i in range(N):
F[find(i)].append(i)
Parent=[-1]*N
Child=[[] for i in range(N)]
Children=[1]*N
USE=[0]*N
Group2=[i for i in range(N)]
ANS=0
DIS=[1<<60]*N
WS=[0]*N
Childind=[0]*N
for i in range(N):
if find(i)==i:
# 木のHL分解+LCA
ROOT=i
QUE=[ROOT]
Parent[ROOT]=N # ROOTの親を定めておく.
TOP_SORT=[] # トポロジカルソート
DIS[ROOT]=0
while QUE: # トポロジカルソートと同時に親を見つける
x=QUE.pop()
TOP_SORT.append(x)
for to in E[x]:
if Parent[to]==-1:
Parent[to]=x
DIS[to]=DIS[x]+1
Child[x].append(to)
QUE.append(to)
for x in TOP_SORT[::-1]: #(自分を含む)子ノードの数を調べる
if x==ROOT:
break
Children[Parent[x]]+=Children[x]
for x in TOP_SORT: # HL分解によるグループ分け
USE[x]=1
MAX_children=0
select_node=0
for to in E[x]:
if USE[to]==0 and Children[to]>MAX_children:
select_node=to
MAX_children=Children[to]
for to in E[x]:
if USE[to]==0 and to==select_node:
Group2[to]=Group2[x]
def LCA(a,b): # HL分解を利用してLCAを求める
while Group2[a]!=Group2[b]:
if Group2[b]==ROOT:
a=Parent[Group2[a]]
elif Group2[a]==ROOT:
b=Parent[Group2[b]]
elif Children[Parent[Group2[a]]]<Children[Parent[Group2[b]]]:
a=Parent[Group2[a]]
else:
b=Parent[Group2[b]]
if Children[a]>Children[b]:
return a
else:
return b
for x,y in QU[ROOT]:
lca=LCA(x,y)
dx=DIS[x]
dy=DIS[y]
dl=DIS[lca]
if x==lca or y==lca:
ANS+=abs(dx-dy)
else:
ANS+=abs(dx-dl)
ANS+=abs(dy-dl)
now=0
SUM=0
for x in F[ROOT]:
now+=DIS[x]*A[x]
WS[x]+=A[x]
SUM+=A[x]
scoremin=now
for x in TOP_SORT[::-1]:
for c in Child[x]:
WS[x]+=WS[c]
nowind=ROOT
while True:
if nowind==N:
break
if Childind[nowind]==len(Child[nowind]):
kk=WS[nowind]
now+=kk-(SUM-kk)
nowind=Parent[nowind]
else:
Childind[nowind]+=1
toind=Child[nowind][Childind[nowind]-1]
kk=WS[toind]
now+=(SUM-kk)-kk
nowind=toind
scoremin=min(scoremin,now)
ANS+=scoremin
print(ANS)
titia