結果
問題 |
No.1983 [Cherry 4th Tune C] 南の島のマーメイド
|
ユーザー |
👑 ![]() |
提出日時 | 2022-06-12 19:29:15 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 439 ms / 4,000 ms |
コード長 | 7,253 bytes |
コンパイル時間 | 2,568 ms |
コンパイル使用メモリ | 214,764 KB |
最終ジャッジ日時 | 2025-01-29 20:52:28 |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 41 |
コンパイルメッセージ
main.cpp: In function ‘int main()’: main.cpp:295:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 295 | scanf("%d%d",&u,&v); | ~~~~~^~~~~~~~~~~~~~ main.cpp:308:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 308 | scanf("%d%d",&x,&y); | ~~~~~^~~~~~~~~~~~~~
ソースコード
#include<bits/stdc++.h> using namespace std; struct Edge{ int id, source, target; Edge(int id, int source, int target): id(id), source(source), target(target){} // 出力 friend ostream &operator<<(ostream &os, const Edge &e) { return os << "id: " << e.id << ", source: " << e.source << ", target: " << e.target; } }; struct Graph{ using E=Edge; vector<vector<E>> inc; vector<E> edge; Graph(int N=0){ inc.resize(N); } // 頂点数 int order(){return inc.size();} // 辺の数 int size(){return edge.size();} // 頂点を1個追加する. int add_vertex(){ inc.emplace_back(vector<E>()); return inc.size()-1; } // 頂点をk個追加する. vector<int> add_vertices(int k){ vector<int> I; for (; k--; k>=0){ I.emplace_back(add_vertex()); } return I; } // 無向辺 uv を加える. int add_edge(int u, int v){ int i=size(); inc[u].emplace_back(E(i,u,v)); inc[v].emplace_back(E(i,v,u)); edge.emplace_back(E(i,u,v)); return i; } // 無向辺 e を加える. int add_edge(const Edge &e){ return add_edge(e.source, e.target); } // walk を加える. vector<int> add_walk(const vector<int> &walk){ vector<int> J; for (int i=0; i<(int)walk.size()-1; i++){ J.emplace_back(add_edge(walk[i], walk[i+1])); } return J; } Edge get_edge(int j){ return edge[j]; } // cycle を加える. vector<int> add_cycle(const vector<int> &cycle){ vector<int> J=add_walk(cycle); J.emplace_back(add_edge(cycle.back(),cycle.front())); return J; } // 頂点 v を含む連結成分を出力する. vector<int> connected_component(int v){ vector<int> C; vector<bool> T(order(),false); T[v]=true; deque<int> Q{v}; while (!Q.empty()){ int x=Q.front(); Q.pop_front(); C.emplace_back(x); for (E &e:inc[x]){ int t=e.target; if (!T[t]){ T[t]=true; Q.push_back(t); } } } return C; } // u,v は連結かどうかを求める. bool is_connected_vertex(int u, int v){ if (u==v) return true; vector<int> T(order(), false); T[u]=true; deque<int> Q{u}; while (!Q.empty()){ int x=Q.front(); Q.pop_front(); for (E &e:inc[x]){ int t=e.target; if (T[t]==false){ T[t]=true; Q.push_back(t); if (t==v) return true; } } } return false; } // 2 頂点 u,v 間の距離を求める. int distance(int u, int v){ if (u==v) return 0; vector<int> T(order(),-1); T[u]=0; deque<int> Q{u}; while (!Q.empty()){ int x=Q.front(); Q.pop_front(); for (E &e:inc[x]){ int t=e.target; if (T[t]==-1){ T[t]=T[x]+1; Q.push_back(t); if (t==v) return T[t]; } } } return -1; } // 頂点 u 間からの距離を求める. vector<int> distance_all(int u){ vector<int> T(order(),-1); T[u]=0; deque<int> Q{u}; while (!Q.empty()){ int x=Q.front(); Q.pop_front(); for (E &e:inc[x]){ int t=e.target; if (T[t]==-1){ T[t]=T[x]+1; Q.push_back(t); } } } return T; } // u-v 間の最短路を求める (存在しない場合, []). vector<int> shortest_path(int u, int v){ if (u==v) return vector<int>{u}; vector<int> T(order(),-1); deque<int> Q{u}; while (!Q.empty()){ int x=Q.front(); Q.pop_front(); for (auto &e:inc[x]){ int y=e.target; if (T[y]==-1){ T[y]=x; Q.push_back(y); if (y==v){ vector<int> P{v}; int a=v; while (a!=u){ a=T[a]; P.emplace_back(a); } reverse(P.begin(), P.end()); return P; } } } } return vector<int>{}; } }; struct Connected_Component_Decomposition{ vector<vector<int>> component; vector<int> id; public: Connected_Component_Decomposition(Graph &G){ calculate(G); } private: int k; void calculate(Graph &G){ int N=G.order(); component.clear(); id.assign(N,-1); k=0; for (int v=0; v<N; v++){ if (id[v]==-1){ component.emplace_back(vector<int>()); dfs(G,v); k++; } } } void dfs(Graph &G, int v){ id[v]=k; component.back().emplace_back(v); for (auto &e: G.inc[v]){ if (id[e.target]==-1) dfs(G,e.target); } } public: inline int component_number() const {return component.size();} inline bool is_connected(const int &u, const int &v) const {return id[u]==id[v];} }; struct Lowlink{ vector<bool> used, bridge, articulation; vector<int> ord, low; Lowlink(Graph &G){ int N=G.order(), M=G.size(); used.assign(N,false); ord.assign(N,0); low.assign(N,0); bridge.assign(M,false); articulation.assign(N,false); int k=0; for (int i=0; i<N; i++){ if (!used[i]) k=dfs(G,i,k,-1); } } private: int dfs(Graph &G, int v, int k, int par){ used[v]=true; ord[v]=k++; low[v]=ord[v]; bool is_arti=false; int child=0; for (auto &e:G.inc[v]){ if (!used[e.target]){ child++; k=dfs(G,e.target,k,v); low[v]=min(low[v], low[e.target]); if (par!=-1 && ord[v]<=low[e.target]) is_arti=true; if (ord[v]<low[e.target]) bridge[e.id]=true; }else if (e.target!=par){ low[v]=min(low[v], ord[e.target]); } } if (par==-1 && child>=2) is_arti=true; if (is_arti) articulation[v]=true; return k; } }; int main(){ int N,M,Q; cin >> N >> M >> Q; Graph G(N+1); int u,v; for (int j=0; j<M; j++){ scanf("%d%d",&u,&v); G.add_edge(u,v); } Lowlink L(G); Graph H(N+1); for (int j=0; j<M; j++){ if (L.bridge[j]){H.add_edge(G.get_edge(j));} } Connected_Component_Decomposition C(H); int x,y; for (int q=0; q<Q; q++){ scanf("%d%d",&x,&y); if (C.is_connected(x,y)) cout << "Yes" << "\n"; else cout << "No" << endl; } }