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;
}
相关推荐
啊我不会诶11 小时前
24ICPC成都站补题
数据结构·算法
渡我白衣12 小时前
list 与 forward_list:一场 STL 中的“链表哲学”之争
数据结构·c++·list
2401_8414956414 小时前
【计算机视觉】基于数学形态学的保留边缘图像去噪
人工智能·python·算法·计算机视觉·图像去噪·数学形态学·边缘保留
十八岁讨厌编程14 小时前
【算法训练营Day30】动态规划part6
算法·动态规划
CoderYanger14 小时前
优选算法-双指针:2.复写零
java·后端·算法·leetcode·职场和发展
charlie11451419115 小时前
理解C++20的革命特性——协程支持2:编写简单的协程调度器
c++·学习·算法·设计模式·c++20·协程·调度器
hadage23315 小时前
--- 常见排序算法汇总 ---
算法·排序算法
Mrs.Gril15 小时前
目标检测:yolov7算法在RK3588上部署
算法·yolo·目标检测
WWZZ202517 小时前
ORB_SLAM2原理及代码解析:单应矩阵H、基础矩阵F求解
线性代数·算法·计算机视觉·机器人·slam·基础矩阵·单应矩阵
2401_8414956417 小时前
【计算机视觉】分水岭实现医学诊断
图像处理·人工智能·python·算法·计算机视觉·分水岭算法·医学ct图像分割