题解 [ABC304E] Good Graph
大家好,我是 CQ-C2024 蒟蒻 CJH。
题意
给你一个有 $N$ 个点 $M$ 条边的无向图。
注意:图中可能会有重边和自环。
接着有 $K$ 个约束条件,约束 $x_i$ 到 $y_i$ 之间没有一条路径可以到达。
最后有 $Q$ 个询问,询问如果连接 $p_i$ 和 $q_i$,是否满足所有的约束条件。
分析
经过观察,不难发现这是一道维护连通性的题,于是就很容易想到了并查集。
首先建图时把每一条边上的两点在并查集中合并。
接着给出了 $K$ 个约束条件,只需要把约束的两个点所对应的连通块标记一下即可。因为连通块的值可能很大,数组存不下,这里就需要使用 map。
最后 $Q$ 个询问,如果两个连接的点所在的连通块被标记,那么就无法满足约束条件,否则就满足。
时间复杂度 $O(Q \log n)$。
代码
//the code is from chenjh
#include<cstdio>
#include<map>
#include<utility>
#define MAXN 200002
#define mp std::make_pair
int n,m,k,q;
int fa[MAXN];
inline int find(const int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
inline void merge(int x,int y){x=find(x),y=find(y);if(x!=y)fa[x]=y;}
std::map<std::pair<int,int>,bool> M;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=0,u,v;i<m;i++){
scanf("%d%d",&u,&v);
merge(u,v);//并查集将 u 和 v 进行合并。
}
scanf("%d",&k);
for(int i=0,u,v;i<k;i++){
scanf("%d%d",&u,&v);
M[mp(find(u),find(v))]=M[mp(find(v),find(u))]=1;//标记两个点所在的连通块。
}
scanf("%d",&q);
for(int i=0,u,v;i<q;i++){
scanf("%d%d",&u,&v);
puts(M.find(mp(find(u),find(v)))!=M.end()||M.find(mp(find(v),find(u)))!=M.end()?"No":"Yes");//如果被标记为 No,否则为 Yes。
}
return 0;
}

浙公网安备 33010602011771号