连通块中点的数量、堆箱子(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];
    }
}
相关推荐
j7~1 小时前
【算法】专题二:滑动窗口之水果成蓝,找到字符串中所有字⺟异位词等算法题
c++·算法·滑动窗口·水果成蓝·最小字串覆盖·优选算法精选
木木子221 小时前
# 星座配对深度解析:Select 长列表选择器、矩阵评分算法与数据驱动建议
java·算法·华为·矩阵·harmonyos
大鱼>2 小时前
AI+货物追踪:跨境电商包裹追踪系统
人工智能·深度学习·算法·机器学习
大鱼>2 小时前
AI+货物追踪:全链路货物可视化追踪系统
人工智能·深度学习·算法·机器学习
大江东去浪淘尽千古风流人物2 小时前
【SLAM】slam高动态位姿估计全链路拆解
算法·面试·职场和发展·视觉里程计·slam·vio·大疆
想你依然心痛2 小时前
量子计算对嵌入式密码学的挑战与后量子算法准备
算法·密码学·量子计算
Jerry6 小时前
LeetCode 28. 找出字符串中第一个匹配项的下标
算法
Jerry7 小时前
LeetCode 459. 重复的子字符串
算法
海石10 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode