Reachability Query(Union-Find)

Time Limit: 3 sec / Memory Limit: 1024 MiB

Score : 450 points

Problem Statement

You are given an undirected graph with N vertices and zero edges.

The vertices are numbered 1,2,...,N, and initially all vertices are white.

Process a total of Q queries of the following three types:

  • Type 1 : Add an undirected edge connecting vertices u and v.
  • Type 2 : If vertex v is white, change it to black; if it is black, change it to white.
  • Type 3 : Determine whether a black vertex can be reached from vertex v by traversing zero or more edges; report Yes if reachable, and No otherwise.

Constraints

  • All input values are integers.
  • 1≤N≤
  • 1≤Q≤
  • Type 1 queries satisfy the following constraints:
    • 1≤u<v≤N
    • For each query, no edge connecting u and v has been added before that query.
  • Type 2,3 queries satisfy the following constraints:
    • 1≤v≤N

Input

The input is given from Standard Input in the following format:

复制代码
N 𝑄
Query1​
Query2​
⋮
QueryQ​

where Queryi​ represents the i-th query.

Type 1 queries are given in the following format:

复制代码
1 u v

Type 2 queries are given in the following format:

复制代码
2 v

Type 3 queries are given in the following format:

复制代码
3 v

Output

For each type 3 query, output the answer as follows:

  • Yes if a black vertex can be reached from vertex v by traversing zero or more edges;
  • No if no black vertex can be reached from vertex v by traversing zero or more edges.

Sample Input 1

cpp 复制代码
5 12
3 2
2 2
3 2
1 2 5
1 3 4
3 4
3 5
1 4 5
1 1 3
3 1
2 2
3 1

Sample Output 1

复制代码
No
Yes
No
Yes
Yes
No

In this input, the graph initially has five vertices and zero edges.

This input contains 12 queries.

  • The 1st query is 3 2.
    • At this point, no black vertex can be reached from vertex 2 by traversing zero or more edges, so report No.
  • The 2nd query is 2 2.
    • Vertex 22 is white, so change it to black.
  • The 3rd query is 3 2.
    • At this point, black vertex 22 can be reached from vertex 2 by traversing zero or more edges. Therefore, report Yes.
  • The 4th query is 1 2 5.
    • Add an edge connecting vertices 2,5.
  • The 5th query is 1 3 4.
    • Add an edge connecting vertices 3,4.
  • The 6th query is 3 4.
    • At this point, no black vertex can be reached from vertex 4 by traversing zero or more edges, so report No.
  • The 7th query is 3 5.
    • At this point, black vertex 2 can be reached from vertex 5 by traversing zero or more edges. Therefore, report Yes.
  • The 8th query is 1 4 5.
    • Add an edge connecting vertices 4,5.
  • The 9th query is 1 1 3.
    • Add an edge connecting vertices 1,3.
  • The 10th query is 3 1.
    • At this point, black vertex 2 can be reached from vertex 1 by traversing zero or more edges. Therefore, report Yes.
  • The 11th query is 2 2.
    • Vertex 2 is black, so change it to white.
  • The 12th query is 3 1.
    • At this point, no black vertex can be reached from vertex 1 by traversing zero or more edges, so report No.

思路分析

  1. 初始化:使用并查集(Union-Find)数据结构来管理连通分量。每个顶点初始时独立为一个分量,颜色均为白色,黑色计数为零。

  2. 处理查询

    • 类型1(添加边):合并两个顶点所在的连通分量,合并时黑色计数相加。

    • 类型2(切换颜色):改变顶点颜色,并更新所在分量的黑色计数。白色变黑色时计数增加,黑色变白色时计数减少。

    • 类型3(检查可达性):检查顶点所在分量的黑色计数是否大于零,若是则输出"Yes",否则输出"No"。

  3. 效率优化:并查集通过路径压缩和按秩合并优化,确保每次操作的时间复杂度接近常数,适用于大规模输入。

代码

cpp 复制代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+5;
vector<int>fa(N),rankk(N,0),color(N,0),cnt_black(N,0);
int n,q,op,u,v;
int find(int x){
    if(fa[x]!=x){
        fa[x]=find(fa[x]);
    }
    return fa[x];
}
void unionset(int x,int y){
    int rx=find(x),ry=find(y);
    if(rx==ry)return;
    if(rankk[rx]>rankk[ry]){
        fa[ry]=rx;
        cnt_black[rx]+=cnt_black[ry];
    }
    else{
        if(rankk[rx]==rankk[ry])rankk[ry]++;
        fa[rx]=ry;
        cnt_black[ry]+=cnt_black[rx];
    }
}
vector<int>black(N,0);
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n>>q;
    for(int i=1;i<=n;i++){
        fa[i]=i;
    }
    while(q--){
        cin>>op;
        if(op==1){
            cin>>u>>v;
            unionset(u,v);
        }
        else if(op==2){
            cin>>v;
            int c=color[v];
            if(c==0){
                color[v]=1;
                int root=find(v);
                cnt_black[root]++;
            }
            else{
                color[v]=0;
                int root=find(v);
                cnt_black[root]--;
            }
        }
        else{
            cin>>v;
            int root=find(v);
            if(cnt_black[root]>0){
                cout<<"Yes\n";
            }
            else{
                cout<<"No\n";
            }
        }
    }
    return 0;
}
相关推荐
让我们一起加油好吗2 小时前
【基础算法】初识搜索:递归型枚举与回溯剪枝
c++·算法·剪枝·回溯·洛谷·搜索
郝学胜-神的一滴2 小时前
Horse3D游戏引擎研发笔记(七):在QtOpenGL环境下,使用改进的Uniform变量管理方式绘制多彩四边形
c++·3d·unity·游戏引擎·图形渲染·虚幻·unreal engine
stbomei4 小时前
基于 MATLAB 的信号处理实战:滤波、傅里叶变换与频谱分析
算法·matlab·信号处理
德先生&赛先生5 小时前
LeetCode-542. 01 矩阵
算法·leetcode·矩阵
HAH-HAH5 小时前
【洛谷】P2197【模板】Nim 游戏
算法·游戏
lichkingyang5 小时前
最近遇到的几个JVM问题
java·jvm·算法
feifeigo1236 小时前
matlab中随机森林算法的实现
算法·随机森林·matlab
躲着人群7 小时前
次短路&&P2865 [USACO06NOV] Roadblocks G题解
c语言·数据结构·c++·算法·dijkstra·次短路
一只鲲7 小时前
56 C++ 现代C++编程艺术5-万能引用
开发语言·c++