結果
問題 | No.922 東北きりきざむたん |
ユーザー |
![]() |
提出日時 | 2019-11-09 20:08:06 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 836 ms / 2,000 ms |
コード長 | 3,847 bytes |
コンパイル時間 | 168 ms |
コンパイル使用メモリ | 82,176 KB |
実行使用メモリ | 221,824 KB |
最終ジャッジ日時 | 2024-09-15 04:48:00 |
合計ジャッジ時間 | 12,879 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 4 |
other | AC * 26 |
ソースコード
# coding: utf-8# Your code here!class LCA_doubling:"""parent: ダブリングテーブルdepth: 元の深さ"""def __init__(self,g,roots): #g: graphdef dfs(v,p): #p: parent of vif p != -1: self.depth[v] = self.depth[p]+1for c in g[v]:if c == p: continueself.parent[0][c] = vdfs(c,v)returndef doubling_make_table(N,logN,Table):for i in range(1,logN):for j, Tiij in enumerate(Table[i-1]):if Tiij != -1:Table[i][j] = Table[i-1][Tiij]N = len(g)self.logN = len(bin(N))-2self.parent = [[-1]*N for _ in range(self.logN)]self.depth = [0]*(N) #ノードの深さfor i in roots: dfs(i,-1) #root を根とする木と見て計算doubling_make_table(N, self.logN, self.parent) #ダブリングのテープル構築def getLCA(self,u,v): #u,vのLCAを返すif self.depth[u] > self.depth[v]: u,v = v,u #vが深いdd = self.depth[v] - self.depth[u]for k in range(self.logN-1,-1,-1):if (dd >> k) & 1: v = self.parent[k][v]if u == v: return u;for k in range(self.logN-1,-1,-1):if self.parent[k][u] != self.parent[k][v]:u,v = self.parent[k][u], self.parent[k][v]return self.parent[0][u];def getdepth(self,u): #uの深さを返すreturn self.depth[u]##########class UnionFind:def __init__(self, n):self.parent = list(range(n)) #親ノードself.size = [1]*n #グループの要素数def root(self, x): #root(x): xの根ノードを返す.while self.parent[x] != x:self.parent[x] = self.parent[self.parent[x]]x = self.parent[x]return xdef merge(self, x, y): #merge(x,y): xのいる組とyのいる組をまとめるx, y = self.root(x), self.root(y)if x == y: return Falseif self.size[x] < self.size[y]: x,y=y,x #xの要素数が大きいようにself.size[x] += self.size[y] #xの要素数を更新self.parent[y] = x #yをxにつなぐreturn Truedef issame(self, x, y): #same(x,y): xとyが同じ組ならTruereturn self.root(x) == self.root(y)def getsize(self,x): #size(x): xのいるグループの要素数を返すreturn self.size[self.root(x)]##############import syssys.setrecursionlimit(10**6)readline = sys.stdin.readline#n = int(input())n,m,q = [int(i) for i in readline().split()]g = [[] for _ in range(n)]UF = UnionFind(n)for i in range(m):a,b = [int(i)-1 for i in readline().split()]g[a].append(b)g[b].append(a)UF.merge(a,b)Same = []wt = [0]*n#print(ab)from collections import Countersum_of_wt = Counter()for _ in range(q):a,b = [int(i)-1 for i in readline().split()]if UF.issame(a,b):Same.append((a,b))else:sum_of_wt[UF.root(a)] += 1sum_of_wt[UF.root(b)] += 1wt[a] += 1wt[b] += 1def center_of_points(g,wt,roots): #p: parent of vdef dfs(v,p,n):dist = 0maxdiff = 0for c in g[v]:if c == p: continuew,d,m = dfs(c,v,n)wt[v] += wdist += w+dmaxdiff = max(maxdiff,m+(2*w-n))return wt[v], dist, maxdiffres = 0for r in roots:w,d,m = dfs(r,-1,sum_of_wt[r])res += d-mreturn resroots = [i for i,x in enumerate(UF.parent) if i == x]LCA = LCA_doubling(g,roots)#print(roots)ans = center_of_points(g,wt,roots)#print(ans)for a,b in Same:ans += LCA.getdepth(a) + LCA.getdepth(b) - 2*LCA.getdepth(LCA.getLCA(a,b))print(ans)