結果
問題 | No.922 東北きりきざむたん |
ユーザー | vwxyz |
提出日時 | 2021-11-07 20:08:30 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 839 ms / 2,000 ms |
コード長 | 35,326 bytes |
コンパイル時間 | 367 ms |
コンパイル使用メモリ | 82,032 KB |
実行使用メモリ | 238,020 KB |
最終ジャッジ日時 | 2024-11-14 13:09:34 |
合計ジャッジ時間 | 18,247 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 57 ms
64,120 KB |
testcase_01 | AC | 54 ms
63,376 KB |
testcase_02 | AC | 54 ms
63,620 KB |
testcase_03 | AC | 55 ms
63,332 KB |
testcase_04 | AC | 109 ms
77,884 KB |
testcase_05 | AC | 65 ms
72,208 KB |
testcase_06 | AC | 128 ms
78,880 KB |
testcase_07 | AC | 113 ms
78,388 KB |
testcase_08 | AC | 121 ms
78,080 KB |
testcase_09 | AC | 643 ms
147,196 KB |
testcase_10 | AC | 457 ms
94,728 KB |
testcase_11 | AC | 519 ms
125,740 KB |
testcase_12 | AC | 707 ms
196,372 KB |
testcase_13 | AC | 378 ms
108,424 KB |
testcase_14 | AC | 839 ms
199,784 KB |
testcase_15 | AC | 682 ms
209,944 KB |
testcase_16 | AC | 766 ms
146,248 KB |
testcase_17 | AC | 773 ms
147,052 KB |
testcase_18 | AC | 798 ms
147,172 KB |
testcase_19 | AC | 783 ms
148,056 KB |
testcase_20 | AC | 778 ms
145,916 KB |
testcase_21 | AC | 528 ms
133,208 KB |
testcase_22 | AC | 523 ms
132,816 KB |
testcase_23 | AC | 769 ms
144,440 KB |
testcase_24 | AC | 802 ms
144,828 KB |
testcase_25 | AC | 767 ms
143,900 KB |
testcase_26 | AC | 780 ms
145,984 KB |
testcase_27 | AC | 760 ms
145,820 KB |
testcase_28 | AC | 788 ms
238,020 KB |
testcase_29 | AC | 607 ms
151,552 KB |
ソースコード
import heapq import random from collections import defaultdict,deque class Graph: def __init__(self,V,edges=False,graph=False,directed=False,weighted=False): self.V=V self.directed=directed self.weighted=weighted if not graph: self.edges=edges self.graph=[[] for i in range(self.V)] if weighted: for i,j,d in self.edges: self.graph[i].append((j,d)) if not self.directed: self.graph[j].append((i,d)) else: for i,j in self.edges: self.graph[i].append(j) if not self.directed: self.graph[j].append(i) else: self.graph=graph self.edges=[] for i in range(self.V): if self.weighted: for j,d in self.graph[i]: if self.directed or not self.directed and i<=j: self.edges.append((i,j,d)) else: for j in self.graph[i]: if self.directed or not self.directed and i<=j: self.edges.append((i,j)) def SIV_BFS(self,s,bfs_tour=False,bipartite_graph=False,linked_components=False,parents=False,unweighted_dist=False,weighted_dist=False): seen=[False]*self.V seen[s]=True if bfs_tour: bt=[s] if linked_components: lc=[s] if parents: ps=[None]*self.V if unweighted_dist or bipartite_graph: uwd=[float('inf')]*self.V uwd[s]=0 if weighted_dist: wd=[float('inf')]*self.V wd[s]=0 queue=deque([s]) while queue: x=queue.popleft() for y in self.graph[x]: if self.weighted: y,d=y if not seen[y]: seen[y]=True queue.append(y) if bfs_tour: bt.append(y) if linked_components: lc.append(y) if parents: ps[y]=x if unweighted_dist or bipartite_graph: uwd[y]=uwd[x]+1 if weighted_dist: wd[y]=wd[x]+d if bipartite_graph: bg=[[],[]] for tpl in self.edges: i,j=tpl[:2] if self.weighted else tpl if type(uwd[i])==float or type(uwd[j])==float: continue if not uwd[i]%2^uwd[j]%2: bg=False break else: for x in range(self.V): if type(uwd[x])==float: continue bg[uwd[x]%2].append(x) tpl=() if bfs_tour: tpl+=(bt,) if bipartite_graph: tpl+=(bg,) if linked_components: tpl+=(lc,) if parents: tpl+=(ps,) if unweighted_dist: tpl+=(uwd,) if weighted_dist: tpl+=(wd,) if len(tpl)==1: tpl=tpl[0] return tpl def MIV_BFS(self,initial_vertices=False,bipartite_graph=False,linked_components=False,parents=False): if not initial_vertices: initial_vertices=[i for i in range(self.V)] seen=[False]*self.V if bipartite_graph: bg=[None]*self.V cnt=-1 if linked_components: lc=[] if parents: ps=[None]*self.V for s in initial_vertices: if seen[s]: continue seen[s]=True if bipartite_graph: cnt+=1 bg[s]=(cnt,0) if linked_components: lc.append([s]) queue=deque([s]) while queue: x=queue.popleft() for y in self.graph[x]: if self.weighted: y,d=y if not seen[y]: seen[y]=True queue.append(y) if bipartite_graph: bg[y]=(cnt,bg[x][1]^1) if linked_components: lc[-1].append(y) if parents: ps[y]=x if bipartite_graph: bg_=bg bg=[[[],[]] for i in range(cnt+1)] for tpl in self.edges: i,j=tpl[:2] if self.weighted else tpl if not bg_[i][1]^bg_[j][1]: bg[bg_[i][0]]=False for x in range(self.V): if bg[bg_[x][0]]: bg[bg_[x][0]][bg_[x][1]].append(x) tpl=() if bipartite_graph: tpl+=(bg,) if linked_components: tpl+=(lc,) if parents: tpl+=(ps,) if len(tpl)==1: tpl=tpl[0] return tpl def SIV_DFS(self,s,bipartite_graph=False,cycle_detection=False,directed_acyclic=False,euler_tour=False,linked_components=False,parents=False,postorder=False,preorder=False,subtree_size=False,topological_sort=False,unweighted_dist=False,weighted_dist=False): seen=[False]*self.V finished=[False]*self.V if directed_acyclic or cycle_detection or topological_sort: dag=True if euler_tour: et=[] if linked_components: lc=[] if parents or cycle_detection or subtree_size: ps=[None]*self.V if postorder or topological_sort: post=[] if preorder: pre=[] if subtree_size: ss=[1]*self.V if unweighted_dist or bipartite_graph: uwd=[float('inf')]*self.V uwd[s]=0 if weighted_dist: wd=[float('inf')]*self.V wd[s]=0 stack=[(s,0)] if self.weighted else [s] while stack: if self.weighted: x,d=stack.pop() else: x=stack.pop() if not seen[x]: seen[x]=True stack.append((x,d) if self.weighted else x) if euler_tour: et.append(x) if linked_components: lc.append(x) if preorder: pre.append(x) for y in self.graph[x]: if self.weighted: y,d=y if not seen[y]: stack.append((y,d) if self.weighted else y) if parents or cycle_detection or subtree_size: ps[y]=x if unweighted_dist or bipartite_graph: uwd[y]=uwd[x]+1 if weighted_dist: wd[y]=wd[x]+d elif not finished[y]: if (directed_acyclic or cycle_detection or topological_sort) and dag: dag=False if cycle_detection: cd=(y,x) elif not finished[x]: finished[x]=True if euler_tour: et.append(~x) if postorder or topological_sort: post.append(x) if subtree_size: for y in self.graph[x]: if self.weighted: y,d=y if y==ps[x]: continue ss[x]+=ss[y] if bipartite_graph: bg=[[],[]] for tpl in self.edges: i,j=tpl[:2] if self.weighted else tpl if type(uwd[i])==float or type(uwd[j])==float: continue if not uwd[i]%2^uwd[j]%2: bg=False break else: for x in range(self.V): if type(uwd[x])==float: continue bg[uwd[x]%2].append(x) tpl=() if bipartite_graph: tpl+=(bg,) if cycle_detection: if dag: cd=[] else: y,x=cd cd=self.Route_Restoration(y,x,ps) tpl+=(cd,) if directed_acyclic: tpl+=(dag,) if euler_tour: tpl+=(et,) if linked_components: tpl+=(lc,) if parents: tpl+=(ps,) if postorder: tpl+=(post,) if preorder: tpl+=(pre,) if subtree_size: tpl+=(ss,) if topological_sort: if dag: tp_sort=post[::-1] else: tp_sort=[] tpl+=(tp_sort,) if unweighted_dist: tpl+=(uwd,) if weighted_dist: tpl+=(wd,) if len(tpl)==1: tpl=tpl[0] return tpl def MIV_DFS(self,initial_vertices=False,bipartite_graph=False,cycle_detection=False,directed_acyclic=False,euler_tour=False,linked_components=False,parents=False,postorder=False,preorder=False,subtree_size=False,topological_sort=False,unweighted_dist=False,weighted_dist=False): if not initial_vertices: initial_vertices=[s for s in range(self.V)] seen=[False]*self.V finished=[False]*self.V if bipartite_graph: bg=[None]*self.V cnt=-1 if directed_acyclic or cycle_detection or topological_sort: dag=True if euler_tour: et=[] if linked_components: lc=[] if parents or cycle_detection or subtree_size: ps=[None]*self.V if postorder or topological_sort: post=[] if preorder: pre=[] if subtree_size: ss=[1]*self.V if unweighted_dist: uwd=[float('inf')]*self.V if weighted_dist: wd=[float('inf')]*self.V for s in initial_vertices: if seen[s]: continue if bipartite_graph: cnt+=1 bg[s]=(cnt,0) if linked_components: lc.append([]) if unweighted_dist: uwd[s]=0 if weighted_dist: wd[s]=0 stack=[(s,0)] if self.weighted else [s] while stack: if self.weighted: x,d=stack.pop() else: x=stack.pop() if not seen[x]: seen[x]=True stack.append((x,d) if self.weighted else x) if euler_tour: et.append(x) if linked_components: lc[-1].append(x) if preorder: pre.append(x) for y in self.graph[x]: if self.weighted: y,d=y if not seen[y]: stack.append((y,d) if self.weighted else y) if bipartite_graph: bg[y]=(cnt,bg[x][1]^1) if parents or cycle_detection or subtree_size: ps[y]=x if unweighted_dist or bipartite_graph: uwd[y]=uwd[x]+1 if weighted_dist: wd[y]=wd[x]+d elif not finished[y]: if directed_acyclic and dag: dag=False if cycle_detection: cd=(y,x) elif not finished[x]: finished[x]=True if euler_tour: et.append(~x) if postorder or topological_sort: post.append(x) if subtree_size: for y in self.graph[x]: if self.weighted: y,d=y if y==ps[x]: continue ss[x]+=ss[y] if bipartite_graph: bg_=bg bg=[[[],[]] for i in range(cnt+1)] for tpl in self.edges: i,j=tpl[:2] if self.weighted else tpl if not bg_[i][1]^bg_[j][1]: bg[bg_[i][0]]=False for x in range(self.V): if bg[bg_[x][0]]: bg[bg_[x][0]][bg_[x][1]].append(x) tpl=() if bipartite_graph: tpl+=(bg,) if cycle_detection: if dag: cd=[] else: y,x=cd cd=self.Route_Restoration(y,x,ps) tpl+=(cd,) if directed_acyclic: tpl+=(dag,) if euler_tour: tpl+=(et,) if linked_components: tpl+=(lc,) if parents: tpl+=(ps,) if postorder: tpl+=(post,) if preorder: tpl+=(pre,) if subtree_size: tpl+=(ss,) if topological_sort: if dag: tp_sort=post[::-1] else: tp_sort=[] tpl+=(tp_sort,) if unweighted_dist: tpl+=(uwd,) if weighted_dist: tpl+=(wd,) if len(tpl)==1: tpl=tpl[0] return tpl def Tree_Diameter(self,weighted=False): def Farthest_Point(u): dist=self.SIV_BFS(u,weighted_dist=True) if weighted else self.SIV_BFS(u,unweighted_dist=True) fp=0 for i in range(self.V): if dist[fp]<dist[i]: fp=i return fp,dist[fp] u,d=Farthest_Point(0) v,d=Farthest_Point(u) return u,v,d def SCC(self): reverse_graph=[[] for i in range(self.V)] for tpl in self.edges: i,j=tpl[:2] if self.weighted else tpl reverse_graph[j].append(i) postorder=self.MIV_DFS(postorder=True) scc=[] seen=[False]*self.V for s in postorder[::-1]: if seen[s]: continue queue=deque([s]) seen[s]=True lst=[] while queue: x=queue.popleft() lst.append(x) for y in reverse_graph[x]: if self.weighted: y,d=y if not seen[y]: seen[y]=True queue.append(y) scc.append(lst) return scc def Build_LCA(self,s): self.lca_euler_tour,self.lca_parents,depth=self.SIV_DFS(s,euler_tour=True,parents=True,unweighted_dist=True) self.lca_dfs_in_index=[None]*self.V self.lca_dfs_out_index=[None]*self.V for i,x in enumerate(self.lca_euler_tour): if x>=0: self.lca_dfs_in_index[x]=i else: self.lca_dfs_out_index[~x]=i self.ST=Segment_Tree(2*self.V,lambda x,y:min(x,y),self.V) lst=[None]*(2*self.V) for i in range(2*self.V-1): if self.lca_euler_tour[i]>=0: lst[i]=depth[self.lca_euler_tour[i]] else: lst[i]=depth[self.lca_parents[~self.lca_euler_tour[i]]] lst[2*self.V-1]=-1 self.ST.Build(lst) def LCA(self,a,b): m=min(self.lca_dfs_in_index[a],self.lca_dfs_in_index[b]) M=max(self.lca_dfs_in_index[a],self.lca_dfs_in_index[b]) x=self.lca_euler_tour[self.ST.Fold_Index(m,M+1)] if x>=0: return x else: return self.lca_parents[~x] def Build_HLD(self,s): self.hld_parents,size,self.hld_depth=self.SIV_DFS(s,parents=True,subtree_size=True,unweighted_dist=True) stack=[s] self.hld_tour=[] self.hld_path_parents=[None]*self.V self.hld_path_parents[s]=s while stack: x=stack.pop() self.hld_tour.append(x) max_size=0 max_size_y=None for y in self.graph[x]: if self.weighted: y,d=y if y==self.hld_parents[x]: continue if max_size<size[y]: max_size=size[y] max_size_y=y for y in self.graph[x]: if self.weighted: y,d=y if y==self.hld_parents[x]: continue if y!=max_size_y: stack.append(y) self.hld_path_parents[y]=y if max_size_y!=None: stack.append(max_size_y) self.hld_path_parents[max_size_y]=self.hld_path_parents[x] self.hld_tour_idx=[None]*self.V for i in range(self.V): self.hld_tour_idx[self.hld_tour[i]]=i def HLD(self,a,b,edge=False): L,R=[],[] while self.hld_path_parents[a]!=self.hld_path_parents[b]: if self.hld_depth[self.hld_path_parents[a]]<self.hld_depth[self.hld_path_parents[b]]: R.append((self.hld_tour_idx[self.hld_path_parents[b]],self.hld_tour_idx[b]+1)) b=self.hld_parents[self.hld_path_parents[b]] else: L.append((self.hld_tour_idx[a]+1,self.hld_tour_idx[self.hld_path_parents[a]])) a=self.hld_parents[self.hld_path_parents[a]] if edge: if self.hld_depth[a]!=self.hld_depth[b]: retu=L+[(self.hld_tour_idx[a]+1,self.hld_tour_idx[b]+1)]+R[::-1] else: retu=L+R[::-1] else: if self.hld_depth[a]<self.hld_depth[b]: retu=L+[(self.hld_tour_idx[a],self.hld_tour_idx[b]+1)]+R[::-1] else: retu=L+[(self.hld_tour_idx[a]+1,self.hld_tour_idx[b])]+R[::-1] return retu def Build_Hash(self,s,random_number=False,mod=False,rerooting=False): self.bottom_hash=[None]*self.V if random_number: self.hash_random_number=random_number else: self.hash_random_number=[random.randint(1,10**10) for i in range(self.V)] if mod: self.hash_mod=mod else: self.hash_mod=(1<<61)-1 parents,postorder,preorder=self.SIV_DFS(s,parents=True,postorder=True,preorder=True) for x in postorder: level=0 for y in self.graph[x]: if self.weighted: y,d=y if y==parents[x]: continue h,l=self.bottom_hash[y] level=max(level,l+1) ha=1 for y in self.graph[x]: if self.weighted: y,d=y if y==parents[x]: continue h,l=self.bottom_hash[y] ha*=h+self.hash_random_number[l] ha%=self.hash_mod self.bottom_hash[x]=(ha,level) if rerooting: self.top_hash=[None]*self.V self.top_hash[s]=(1,-1) for x in preorder: children=[y for y,d in self.graph[x] if y!=parents[x]] if self.weighted else [y for y in self.graph[x] if y!=parents[x]] if children: l=len(children) l_lst,r_lst=[None]*(l+1),[None]*(l+1) l_lst[0],r_lst[l]=(1,-1),(1,-1) for i in range(1,l+1): h0,l0=l_lst[i-1] h1,l1=self.bottom_hash[children[i-1]] l_lst[i]=(h0*(h1+self.hash_random_number[l1])%self.hash_mod,max(l0,l1)) for i in range(l-1,-1,-1): h0,l0=r_lst[i+1] h1,l1=self.bottom_hash[children[i]] r_lst[i]=(h0*(h1+self.hash_random_number[l1])%self.hash_mod,max(l0,l1)) for i in range(l): if x==s: ha,level=1,0 else: ha,level=self.top_hash[x] h0,l0=l_lst[i] h1,l1=r_lst[i+1] ha*=h0*h1 level=max(level,l0+1,l1+1) ha+=self.hash_random_number[level] ha%=self.hash_mod level+=1 self.top_hash[children[i]]=(ha,level) return def Hash(self,root,subtree=False): if subtree: ha,level=self.bottom_hash[root] ha+=self.hash_random_number[level] ha%=self.hash_mod else: h0,l0=self.bottom_hash[root] h1,l1=self.top_hash[root] ha=(h0*h1+self.hash_random_number[max(l0,l1)])%self.hash_mod level=max(l0,l1) return ha,level def Centroid(self,root=0): x=root while True: for y in self.graph[x]: if self.weighted: y,d=y if y==parents[i][x]: continue if S_size[y]*2>S_size[root]: x=y break else: return x def Centroid_Decomposition(self): cd=[] if self.weighted: edges=[(i,j) for i,j,d in self.edges] else: edges=self.edges points=[i for i in range(self.V)] prev_centroid=None stack=[(edges,points,prev_centroid)] while stack: edges,points,prev_centroid=stack.pop() if len(points)==1: if prev_centroid!=None: cd.append((prev_centroid,points[0])) continue G=Graph(len(points),edges=edges) centroid=G.Centroid() if prev_centroid!=None: cd.append((prev_centroid,points[centroid])) parents,tour=G.SIV_DFS(centroid,parents=True,preorder=True) dp=[None]*len(points) edges_lst=[] points_lst=[] for i,x in enumerate(G.graph[centroid]): dp[x]=(i,0) edges_lst.append([]) points_lst.append([points[x]]) for x in tour[1:]: for y in G.graph[x]: if y==parents[x]: continue i,j=dp[x] jj=len(points_lst[i]) edges_lst[i].append((j,jj)) points_lst[i].append(points[y]) dp[y]=(i,jj) centroid=points[centroid] for edges,points in zip(edges_lst,points_lst): stack.append((edges,points,centroid)) return cd def Dijkstra(self,s,route_restoration=False): dist=[float('inf')]*self.V dist[s]=0 hq=[(0,s)] if route_restoration: parents=[None]*self.V while hq: dx,x=heapq.heappop(hq) if dist[x]<dx: continue for y,dy in self.graph[x]: if dist[y]>dx+dy: dist[y]=dx+dy if route_restoration: parents[y]=x heapq.heappush(hq,(dist[y],y)) if route_restoration: return dist,parents else: return dist def Bellman_Ford(self,s,route_restoration=False): dist=[float('inf')]*self.V dist[s]=0 if route_restoration: parents=[None]*self.V for _ in range(self.V-1): for i,j,d in self.edges: if dist[j]>dist[i]+d: dist[j]=dist[i]+d if route_restoration: parents[j]=i if not self.directed and dist[i]>dist[j]+d: dist[i]=dist[j]+d if route_restoration: parents[i]=j negative_cycle=[] for i,j,d in self.edges: if dist[j]>dist[i]+d: negative_cycle.append(j) if not self.directed and dist[i]>dist[j]+d: negative_cycle.append(i) if negative_cycle: is_negative_cycle=[False]*self.V for i in negative_cycle: if is_negative_cycle[i]: continue else: queue=deque([i]) is_negative_cycle[i]=True while queue: x=queue.popleft() for y,d in self.graph[x]: if not is_negative_cycle[y]: queue.append(y) is_negative_cycle[y]=True if route_restoration: parents[y]=x for i in range(self.V): if is_negative_cycle[i]: dist[i]=-float('inf') if route_restoration: return dist,parents else: return dist def Warshall_Floyd(self,route_restoration=False): dist=[[float('inf')]*self.V for i in range(self.V)] for i in range(self.V): dist[i][i]=0 if route_restoration: parents=[[j for j in range(self.V)] for i in range(self.V)] for i,j,d in self.edges: if i==j: continue if dist[i][j]>d: dist[i][j]=d if route_restoration: parents[i][j]=i if not self.directed and dist[j][i]>d: dist[j][i]=d if route_restoration: parents[j][i]=j for k in range(self.V): for i in range(self.V): for j in range(self.V): if dist[i][j]>dist[i][k]+dist[k][j]: dist[i][j]=dist[i][k]+dist[k][j] if route_restoration: parents[i][j]=parents[k][j] for i in range(self.V): if dist[i][i]<0: for j in range(self.V): if dist[i][j]!=float('inf'): dist[i][j]=-float('inf') if route_restoration: for i in range(self.V): if dist[i][i]==0: parents[i][i]=None return dist,parents else: return dist def Route_Restoration(self,s,g,parents): route=[g] while s!=g: if parents[g]==None: route=[] break g=parents[g] route.append(g) route=route[::-1] return route def Kruskal(self): UF=UnionFind(self.V) sorted_edges=sorted(self.edges,key=lambda x:x[2]) minimum_spnning_tree=[] for i,j,d in sorted_edges: if not UF.Same(i,j): UF.Union(i,j) minimum_spnning_tree.append((i,j,d)) return minimum_spnning_tree def Ford_Fulkerson(self,s,t): max_flow=0 residual_graph=[defaultdict(int) for i in range(self.V)] if self.weighted: for i,j,d in self.edges: if not d: continue residual_graph[i][j]+=d if not self.directed: residual_graph[j][i]+=d else: for i,j in self.edges: residual_graph[i][j]+=1 if not self.directed: residual_graph[j][i]+=1 while True: parents=[None]*self.V parents[s]=s seen=[False]*self.V seen[s]=True queue=deque([s]) while queue: x=queue.popleft() for y in residual_graph[x].keys(): if not seen[y]: seen[y]=True queue.append(y) parents[y]=x if y==t: tt=t while tt!=s: residual_graph[parents[tt]][tt]-=1 residual_graph[tt][parents[tt]]+=1 if not residual_graph[parents[tt]][tt]: residual_graph[parents[tt]].pop(tt) tt=parents[tt] max_flow+=1 break else: continue break else: break return max_flow def BFS(self,s): seen=[False]*self.V seen[s]=True queue=deque([s]) while queue: x=queue.popleft() for y in self.graph[x]: if self.weighted: y,d=y if not seen[y]: seen[y]=True queue.append(y) return def DFS(self,s): seen=[False]*self.V finished=[False]*self.V stack=[(s,0)] if self.weighted else [s] while stack: if self.weighted: x,d=stack.pop() else: x=stack.pop() if not seen[x]: seen[x]=True stack.append((x,d) if self.weighted else x) for y in self.graph[x]: if self.weighted: y,d=y if not seen[y]: stack.append((y,d) if self.weighted else y) elif not finished[x]: finished[x]=True return class Segment_Tree: def __init__(self,N,f,e,lst=None): self.f=f self.e=e self.N=N if lst==None: self.segment_tree=[self.e]*2*self.N else: assert len(lst)<=self.N self.segment_tree=[self.e]*self.N+[x for x in lst]+[self.e]*(N-len(lst)) for i in range(self.N-1,0,-1): self.segment_tree[i]=self.f(self.segment_tree[i<<1],self.segment_tree[i<<1|1]) def __getitem__(self,i): if type(i)==int: if -self.N<=i<0: return self.segment_tree[i+self.N*2] elif 0<=i<self.N: return self.segment_tree[i+self.N] else: raise IndexError('list index out of range') else: a,b,c=i.start,i.stop,i.step if a==None or a<-self.N: a=self.N elif self.N<=a: a=self.N*2 elif a<0: a+=self.N*2 else: a+=self.N if b==None or self.N<=b: b=self.N*2 elif b<-self.N: b=self.N elif b<0: b+=self.N*2 else: b+=self.N return self.segment_tree[slice(a,b,c)] def __setitem__(self,i,x): if -self.N<=i<0: i+=self.N*2 elif 0<=i<self.N: i+=self.N else: raise IndexError('list index out of range') self.segment_tree[i]=x while i>1: i>>= 1 self.segment_tree[i]=self.f(self.segment_tree[i<<1],self.segment_tree[i<<1|1]) def Build(self,lst): for i,x in enumerate(lst,self.N): self.segment_tree[i]=x for i in range(self.N-1,0,-1): self.segment_tree[i]=self.f(self.segment_tree[i<<1],self.segment_tree[i<<1|1]) def Fold(self,L=None,R=None): if L==None or L<-self.N: L=self.N elif self.N<=L: L=self.N*2 elif L<0: L+=self.N*2 else: L+=self.N if R==None or self.N<=R: R=self.N*2 elif R<-self.N: R=self.N elif R<0: R+=self.N*2 else: R+=self.N vL=self.e vR=self.e while L<R: if L&1: vL=self.f(vL,self.segment_tree[L]) L+=1 if R&1: R-=1 vR=self.f(self.segment_tree[R],vR) L>>=1 R>>=1 return self.f(vL,vR) def Fold_Index(self,L=None,R=None): if L==None or L<-self.N: L=self.N elif self.N<=L: L=self.N*2 elif L<0: L+=self.N*2 else: L+=self.N if R==None or self.N<=R: R=self.N*2 elif R<-self.N: R=self.N elif R<0: R+=self.N*2 else: R+=self.N if L==R: return None x=self.Fold(L-self.N,R-self.N) while L<R: if L&1: if self.segment_tree[L]==x: i=L break L+=1 if R&1: R-=1 if self.segment_tree[R]==x: i=R break L>>=1 R>>=1 while i<self.N: if self.segment_tree[i]==self.segment_tree[i<<1]: i<<=1 else: i<<=1 i|=1 i-=self.N return i def __str__(self): return '['+', '.join(map(str,self.segment_tree[self.N:]))+']' import sys readline=sys.stdin.readline N,M,Q=map(int,readline().split()) edges=[] for _ in range(M): u,v=map(int,readline().split()) u-=1;v-=1 edges.append((u,v)) G=Graph(N,edges) lc=G.MIV_DFS(linked_components=True) idx=[None]*N for i,lst in enumerate(lc): for j,x in enumerate(lst): idx[x]=(i,j) l=len(lc) edges_lst=[[] for i in range(l)] G=[None]*l depth=[None]*l tour=[None]*l size=[[0]*len(lc[i]) for i in range(l)] parents=[None]*l for u,v in edges: i,ju=idx[u] i,jv=idx[v] edges_lst[i].append((ju,jv)) for i in range(l): G[i]=Graph(len(lc[i]),edges=edges_lst[i]) G[i].Build_LCA(0) parents[i],tour[i],depth[i]=G[i].SIV_DFS(0,parents=True,postorder=True,unweighted_dist=True) ans=0 for _ in range(Q): a,b=map(int,readline().split()) a-=1;b-=1 ia,ja=idx[a] ib,jb=idx[b] if ia==ib: i=ia lca=G[ia].LCA(ja,jb) ans+=depth[i][ja]+depth[i][jb]-2*depth[i][lca] else: size[ia][ja]+=1 size[ib][jb]+=1 for i in range(l): S_size=[s for s in size[i]] for x in tour[i]: for y in G[i].graph[x]: if y==parents[i][x]: continue S_size[x]+=S_size[y] c=G[i].Centroid() depth[i]=G[i].SIV_DFS(c,unweighted_dist=True) for d,s in zip(depth[i],size[i]): ans+=d*s print(ans)