結果
| 問題 |
No.1983 [Cherry 4th Tune C] 南の島のマーメイド
|
| コンテスト | |
| ユーザー |
chestnut_68
|
| 提出日時 | 2022-08-27 22:51:30 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 596 ms / 4,000 ms |
| コード長 | 3,234 bytes |
| コンパイル時間 | 3,863 ms |
| コンパイル使用メモリ | 241,964 KB |
| 実行使用メモリ | 48,256 KB |
| 最終ジャッジ日時 | 2024-10-15 00:45:28 |
| 合計ジャッジ時間 | 19,490 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 41 |
ソースコード
#include <bits/stdc++.h>
#include <atcoder/all>
using namespace atcoder;
using namespace std;
#define rep1(a) for(int z = 0; z < a; z++)
#define rep2(i, a) for(int i = 0; i < a; i++)
#define rep3(i, a, b) for(int i = a; i < b; i++)
#define rep4(i, a, b, c) for(int i = a; i < b; i += c)
#define overload4(a, b, c, d, e, ...) e
#define rep(...) overload4(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__)
const int64_t INF = 1LL<<60;
using mint = modint998244353;
void YN(bool x){
if(x) cout<<"Yes";
else cout<<"No";
cout<<endl;
}
struct Edge {
int to;
};
using Graph = vector<vector<Edge>>;
using P = pair<long, long>;
/* Lowlink: グラフの関節点・橋を列挙する構造体
作成: O(E+V)
関節点の集合: vector<int> aps
橋の集合: vector<P> bridges
*/
struct LowLink {
const Graph &G;
vector<int> used, ord, low;
vector<int> aps; // articulation points
vector<P> bridges;
LowLink(const Graph &G_) : G(G_) {
used.assign(G.size(), 0);
ord.assign(G.size(), 0);
low.assign(G.size(), 0);
int k = 0;
for (int i = 0; i < (int)G.size(); i++) {
if (!used[i]) k = dfs(i, k, -1);
}
sort(aps.begin(), aps.end()); // 必要ならソートする
sort(bridges.begin(), bridges.end()); // 必要ならソートする
}
int dfs(int id, int k, int par) { // id:探索中の頂点, k:dfsで何番目に探索するか, par:idの親
used[id] = true;
ord[id] = k++;
low[id] = ord[id];
bool is_aps = false;
int count = 0; // 子の数
for (auto &e : G[id]) {
if (!used[e.to]) {
count++;
k = dfs(e.to, k, id);
low[id] = min(low[id], low[e.to]);
if (par != -1 && ord[id] <= low[e.to]) is_aps = true;
if (ord[id] < low[e.to]) bridges.emplace_back(min(id, e.to), max(id, e.to)); // 条件を満たすので橋
} else if (e.to != par) { // eが後退辺の時
low[id] = min(low[id], ord[e.to]);
}
}
if (par == -1 && count >= 2) is_aps = true;
if (is_aps) aps.push_back(id);
return k;
}
};
struct UnionFind {
vector<int> par,siz;
UnionFind(int N):par(N),siz(N,1){
for(int i=0;i<N;i++)par[i]=i;
}
void init(int N){
par.resize(N);
siz.assign(N,1);
for(int i=0;i<N;++i)par[i]=i;
}
int root(int x){
if(par[x]==x)return x;
return par[x]=root(par[x]);
}
void unite(int x,int y){
int rx=root(x);
int ry=root(y);
if(rx==ry)return;
if(siz[rx]<siz[ry])swap(rx, ry);
siz[rx]+=siz[ry];
par[ry]=rx;
}
bool same(int x,int y){
int rx=root(x);
int ry=root(y);
return rx==ry;
}
int size(int x){
return siz[root(x)];
}
};
int main(){
int N,M,Q;cin>>N>>M>>Q;
Graph G(N);
UnionFind tree(N);
rep(i,M){
int u,v;cin>>u>>v;
u--,v--;
G[u].push_back({v});
G[v].push_back({u});
}
LowLink L(G);
int m=L.bridges.size();
rep(i,m){
auto u=L.bridges[i].first,v=L.bridges[i].second;
tree.unite(u,v);
}
rep(Q){
int u,v;cin>>u>>v;
u--,v--;
YN(tree.same(u,v));
}
}
chestnut_68