连通块中点的数量、堆箱子(4星)

连通块中点的数量

问题描述

给定一个初始包含 nn 个点,00 条边的图。第 ii 个点的编号为 ii。(1≤i≤n)(1≤i≤n)

现在要进行 mm 次操作,操作共三种:

  • C a b:在点 aa 与点 bb 之间连一条边,a,ba,b 可能相等。
  • Q1 a b:询问点 aa 与点 bb 是否在一个连通块中,a,ba,b 可能相等。
  • Q2 a:询问点 aa 所在连通块中点的数量。

输入格式

第一行输入两个正整数 n,mn,m。(1≤n,m≤105)(1≤n,m≤105)

接下来 mm 行,每行输入包含一种操作。(1≤a,b≤n)(1≤a,b≤n)

输出格式

对于查询 Q1 a b:若 a,ba,b 在一个连通块中,输出 Yes,否则输出 No

对于查询 Q2 a:输出点 aa 所在连通块中点的数量。

样例输入

复制代码
5 7
C 1 2
Q1 1 2
Q2 1
C 2 5
Q2 5
Q1 1 1
Q1 2 3

样例输出

复制代码
Yes
2
3
Yes
No

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.*;


public class Main {

    static int N=100010,mod=998244353;
    static int size[]=new int[N];
    static int p[]=new int[N];
    
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
    static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
    
    public static void main(String[] args) throws IOException { 
        StringTokenizer st=new StringTokenizer(br.readLine());
        int n=Integer.parseInt(st.nextToken()),m=Integer.parseInt(st.nextToken());
        
        for (int i = 1; i <= n; i++) {
			p[i]=i;
			size[i]=1;
		}
        
        for (int i = 0; i < m; i++) {
        	st=new StringTokenizer(br.readLine());
//        	C a b:在点 a 与点 b 之间连一条边,(a,b) 可能相等。
//        	Q1 a b:询问点 a 与点 b 是否在一个连通块中,(a,b) 可能相等。
//        	Q2 a:询问点 a 所在连通块中点的数量。
        	String ope=st.nextToken();
        	int a=Integer.parseInt(st.nextToken());
        	if(st.hasMoreTokens()){
        		int b=Integer.parseInt(st.nextToken());
        		if("C".equals(ope)){
        			if(a==b)continue;
        			union(a,b);
        		}else{
        			if(a==b){
        				bw.write("Yes\n");
        			}else{
        				if(find(a)==find(b)){
        					bw.write("Yes\n");
        				}else{
        					bw.write("No\n");
        				}
        			}       			
        		}
        	}else{
        		int fa=find(a);
        		bw.write(size[fa]+"\n");
        	}

		}
       
        br.close();
        bw.flush();
        bw.close();      
    }
    
    static void union(int a,int b){
    	a=find(a);b=find(b);
    	if(a!=b){
    		p[a]=b;
    		size[b]+=size[a];
    	}
    }
    static int find(int i){
    	if(i!=p[i]){
    		p[i]=find(p[i]);
    	}
    	return p[i];
    }
}

堆箱子(4星)

问题描述

暑假到了,小蓝打完蓝桥杯去工厂兼职,成为了工厂里的搬运工,工厂里面初始有 nn 个箱子平铺在地面上,每个箱子都有一个编号,分别是 1,2,3...n1,2,3...n。由于小蓝喜欢算法竞赛,他想到了一个问题。

现在有 22 种操作,具体操作如下:

  1. 1 a b,11 号操作,将 aa 位置所在的所有箱子搬到 bb 位置所在的箱子上面,已经在相同位置的箱子不能进行此操作。
  2. 2 a ,22 号操作,查询 aa 位置下有多少个箱子。

现在小蓝有 qq 次操作,对于每次操作 22 ,你需要输出结果。

输入格式

第一行二个整数 n,qn,q ,表示箱子的数量和操作次数。

接下来 qq 行,每行输入代表一个具体操作。

输出格式

对所有的操作 22 ,输出其结果。

样例输入

复制代码
6 6
1 4 2
2 2
2 4
1 2 3
2 2
2 4

样例输出

复制代码
0
1
1
2

在第一次操作后,44 下面是 22 号箱子。

在第二次操作后,44 下面是 22 号箱子,22 下面是 33 号箱子。

评测数据规模

1≤n≤3×104,1≤q≤1051≤n≤3×104,1≤q≤105。

复制代码
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.*;


public class Main {

    static int N=3*10010;
    static int size[]=new int[N];//该根节点对应树有多少节点  最下面的节点是根节点
    static int p[]=new int[N];//父节点
    static int d[]=new int[N];//该位置下面有多少个箱子 也就是答案
    
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
    static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
    
    public static void main(String[] args) throws IOException { 
        StringTokenizer st=new StringTokenizer(br.readLine());
        int n=Integer.parseInt(st.nextToken()),q=Integer.parseInt(st.nextToken());
        
        for (int i = 1; i <= n; i++) {
			p[i]=i;
			size[i]=1;
		}
        
        for (int i = 0; i < q; i++) {
        	st=new StringTokenizer(br.readLine());

        	int ope=Integer.parseInt(st.nextToken());
        	if(ope==1){
        		int a=Integer.parseInt(st.nextToken()),b=Integer.parseInt(st.nextToken());
        		//a位置所在的所有箱子搬到b 位置所在的箱子上面
        		//我们只更新a原来的父节点pa的d[fa] 其子节点先不用跟新  我们后续只需要 d[i]=d[i]+d[p[i]];
        		//当然 p[i]也可能没有被更新过 所有我们要在find里更新
        		if(a==b)continue;
            	union(a,b);
        	}else{
        		int a=Integer.parseInt(st.nextToken());
        		find(a);
        		bw.write(d[a]+"\n");
        	}

		}
       
        br.close();
        bw.flush();
        bw.close();      
    }
    
    static void union(int a,int b){
    	a=find(a);b=find(b);
    	if(a!=b){
    		d[a]=size[b];
    		p[a]=b;
    		size[b]+=size[a];
    		
    	}
    }
    static int find(int i){
    	if(i!=p[i]){
    		int v=find(p[i]);
    		d[i]=d[i]+d[p[i]];
    		p[i]=v;
    	}
    	return p[i];
    }
}
相关推荐
蛋先生DX39 分钟前
你瘦不下来但大模型可以:量化原理了解一下
深度学习·算法·llm
(╹◡╹)2 小时前
18.剪枝
算法·机器学习·剪枝
Fa_Mian_Tuan3 小时前
图论基础|邻接矩阵超详细讲解(含无向/有向/带权图+完整可运行C语言代码)
c语言·数据结构·笔记·算法·图论
hanhahai3 小时前
指针与函数(函数指针与指针函数)
算法
ValhallaCoder4 小时前
Leetcode-hot100(2026.08.17)
python·算法·leetcode
泡沫冰@4 小时前
GO 语言基础
开发语言·算法·golang
luj_17685 小时前
元设计的诱惑与现实
c语言·开发语言·c++·经验分享·算法
小星星闪亮登场5 小时前
ST表--倍增思想
开发语言·数据结构·c++·算法·思维
马可家的菠萝6 小时前
Vue3 + Canvas 手绘笔记工程化实践:别把画布只当成一张 PNG
前端·vue.js·算法
watersink6 小时前
机器学习极大似然估计与EM算法
人工智能·算法·机器学习