题解 [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;
}
posted @ 2023-06-05 12:12  Chen_Jinhui  阅读(10)  评论(0)    收藏  举报  来源