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;
}
相关推荐
郝学胜-神的一滴8 小时前
Qt的QSlider控件详解:从API到样式美化
开发语言·c++·qt·程序人生
橘颂TA8 小时前
【剑斩OFFER】算法的暴力美学——连续数组
c++·算法·leetcode·结构与算法
学困昇8 小时前
C++11中的{}与std::initializer_list
开发语言·c++·c++11
郝学胜-神的一滴8 小时前
Qt的QComboBox控件详解:从API到样式定制
开发语言·c++·qt·程序人生·个人开发
星释9 小时前
Rust 练习册 72:多米诺骨牌与回溯算法
开发语言·算法·rust
程序喵大人11 小时前
推荐个C++高性能内存分配器
开发语言·c++·内存分配
zephyr0511 小时前
深入浅出C++多态:从虚函数到动态绑定的完全指南
开发语言·c++
算法与编程之美11 小时前
提升minist的准确率并探索分类指标Precision,Recall,F1-Score和Accuracy
人工智能·算法·机器学习·分类·数据挖掘
MicroTech202512 小时前
微算法科技(NASDAQ :MLGO)混合共识算法与机器学习技术:重塑区块链安全新范式
科技·算法·区块链
码力码力我爱你12 小时前
C++静态变量依赖关系
java·jvm·c++