結果
問題 | No.1983 [Cherry 4th Tune C] 南の島のマーメイド |
ユーザー |
👑 ![]() |
提出日時 | 2022-03-29 23:39:17 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 1,236 ms / 4,000 ms |
コード長 | 7,488 bytes |
コンパイル時間 | 297 ms |
コンパイル使用メモリ | 82,944 KB |
実行使用メモリ | 249,952 KB |
最終ジャッジ日時 | 2024-10-09 06:35:31 |
合計ジャッジ時間 | 27,813 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 41 |
ソースコード
class Graph: __slots__=("edge_number", "adjacent") #入力定義 def __init__(self, N=0): """ N 頂点の空グラフ (多重辺なし) を生成する.""" self.edge_number=0 self.adjacent=[set() for _ in range(N)] #頂点の追加 def add_vertex(self): """ 頂点を追加する. """ self.adjacent.append(set()) return self.order()-1 def add_vertices(self, k): """ 頂点を k 個追加する. k: int """ n=self.order() self.adjacent.extend([set() for _ in range(k)]) return list(range(n,n+k)) #辺の追加 def add_edge(self,u,v): """ 無向辺 uv を加える""" if not self.edge_exist(u,v): self.adjacent[u].add(v) self.adjacent[v].add(u) self.edge_number+=1 return self.edge_number-1 else: return -1 #辺を除く def remove_edge(self,u,v): """ 無向辺 uv が存在するならば除く""" if self.edge_exist(u,v): self.adjacent[u].discard(v) self.adjacent[v].discard(u) self.edge_number-=1 return True else: return False def reset_vertex(self, u): """ 頂点 u に接続している辺を全て消す.""" X=self.adjacent[u].copy() for v in X: self.remove_edge(u,v) #Walkの追加 def add_walk(self,*walk): """ walk=(w[0],...,w[n-1]) に対して, n-1 本の辺 w[i]w[i+1] を加える.""" n=len(walk) for i in range(n-1): self.add_edge(walk[i],walk[i+1]) #Cycleの追加 def add_cycle(self,*cycle): """ cycle=(c[0], ..., c[n-1]) を加える. """ self.add_walk(*cycle) self.add_edge(cycle[-1],cycle[0]) #グラフに辺が存在するか否か def edge_exist(self,u,v): """ 辺 uv が存在するか? """ return v in self.adjacent[u] #近傍 def neighbohood(self,v): """ 頂点 v の近傍を求める. """ return self.adjacent[v] #次数 def degree(self,v): """ 頂点 v の次数を求める. """ if v in self.adjacent[v]: return len(self.adjacent[v])+1 else: return len(self.adjacent[v]) #頂点数 def vertex_count(self): """ グラフの頂点数 (位数) を出力する. """ return len(self.adjacent) def order(self): """ グラフの位数 (頂点数) を出力する. """ return len(self.adjacent) #辺数 def edge_count(self): """ 辺の本数 (サイズ) を出力する.""" return self.edge_number def size(self): """ サイズ (辺の本数) を出力する. """ return self.edge_number #頂点vを含む連結成分 def connected_component(self,v): """ 頂点 v を含む連結成分を出力する.""" from collections import deque T=[0]*self.N; T[v]=1 Q=deque([v]) while Q: u=Q.popleft() for w in self.adjacent[u]: if T[w]==0: T[w]=1 Q.append(w) return [x for x in range(self.N) if T[x]] #距離 def distance(self,u,v): """ 2頂点 u,v 間の距離を求める.""" if u==v: return 0 from collections import deque inf=float("inf") T=[inf]*self.N; T[u]=0 Q=deque([u]) while Q: w=Q.popleft() for x in self.adjacent[w]: if T[x]==inf: T[x]=T[w]+1 Q.append(x) if x==v: return T[x] return inf #ある1点からの距離 def distance_all(self,u): """ 頂点 u からの距離を求める.""" from collections import deque inf=float("inf") T=[inf]*self.N; T[u]=0 Q=deque([u]) while Q: w=Q.popleft() for x in self.adjacent[w]: if T[x]==inf: T[x]=T[w]+1 Q.append(x) return T #最短路 def shortest_path(self,u,v): """ u から v への最短路を求める (存在しない場合は None). """ if u==v: return [u] from collections import deque inf=float("inf") T=[-1]*self.N Q=deque([u]); T[u]=u while Q: w=Q.popleft() for x in self.adjacent[w]: if T[x]==-1: T[x]=w Q.append(x) if x==v: P=[v] a=v while a!=u: a=T[a] P.append(a) return P[::-1] return None def edge_yielder(self): g=self.adjacent for v in range(self.vertex_count()): for w in g[v]: if v<w: yield (v,w) def Lowlink(G, mode=0): """ G の ord, lowlink を求める. G: Graph output: (ord, lowlink) """ from collections import deque N=G.vertex_count() ord=[-1]*N; low=[-1]*N flag=[0]*N adj=G.adjacent parent=[-1]*N #BFSパート for v in range(N): if flag[v]: continue k=0 S=deque([v]) T=[] while S: u=S.pop() if flag[u]: continue T.append(u) ord[u]=k k+=1 flag[u]=1 for w in adj[u]: if not flag[w]: S.append(w) parent[w]=u for u in T: low[u]=ord[u] for w in T[:0:-1]: for x in adj[w]: if w==v or x!=parent[w]: low[w]=min(low[w],low[x],ord[x]) if mode==0: return ord, low else: return ord, low, parent #橋列挙 def Bridge(G): """ G にある橋を列挙する. G: Graph """ ord,low=Lowlink(G) return [(u,v) for u,v in G.edge_yielder() if ord[u]<low[v] or ord[v]<low[u]] def Connected_Component_Decomposition(G, mode=0): """ 連結成分毎に分解する. G: Graph mode: 0→連結成分, 1, 連結成分番号, 2→ (連結成分, 連結成分番号)""" from collections import deque N=G.vertex_count() T=[-1]*N C=[] k=0 for v in range(N): if T[v]==-1: Q=deque([v]); T[v]=k c=[] while Q: u=Q.popleft() c.append(u) for w in G.adjacent[u]: if T[w]==-1: T[w]=k Q.append(w) k+=1 C.append(c) if mode==0: return C elif mode==1: return T else: return C,T #================================================== import sys input=sys.stdin.readline write=sys.stdout.write N,M,Q=map(int,input().split()) G=Graph(N+1) for _ in range(M): u,v=map(int,input().split()) G.add_edge(u,v) H=Graph(N+1) for u,v in Bridge(G): H.add_edge(u,v) Id=Connected_Component_Decomposition(H,1) Ans=[""]*Q for q in range(Q): x,y=map(int,input().split()) Ans[q]="Yes" if Id[x]==Id[y] else "No" write("\n".join(Ans))