冰岛人 pta java (并查集)

合并

路径压缩

例题:L2-2 冰岛人 - 2019年团体程序设计天梯赛-总决赛 (pintia.cn)

实现代码:

import java.util.ArrayList;
import java.util.Scanner;
class Person {
    String firstName;
    String sex;
    public Person(String firstName, String sex) {
        super();
        this.firstName = firstName;
        this.sex = sex;
    }
}
public class Main {
    static int[] tree;
    static ArrayList<Integer> family = new ArrayList<Integer>();
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        ArrayList<String> allName = new ArrayList<String>();
        Person[] per = new Person[N];
        tree = new int[N];	//家庭树,建立并查集
        sc.nextLine();
        //构建家庭树
        for(int i=0;i<N;i++) {
            String Name = sc.nextLine();
            String[] name = Name.split(" ");
            //男后裔
            if(name[1].indexOf("sson")!=-1) {
                name[1] = name[1].replace("sson", "");
                per[i] = new Person(name[0], "m");
            }
            //女后裔
            else if(name[1].indexOf("sdottir")!=-1) {
                name[1] = name[1].replace("sdottir", "");
                per[i] = new Person(name[0], "f");
            }
            //男祖先
            else if(name[1].charAt(name[1].length()-1)=='m') {
                per[i] = new Person(name[0], "m");
            }
            //女祖先
            else if(name[1].charAt(name[1].length()-1)=='f') {
                per[i] = new Person(name[0], "f");
            }
            allName.add(name[0]);	//存储名字
            //根据其父亲是否存在建立并查集队列
            int index = allName.indexOf(name[1]);
            if(index == -1)
                tree[i] = i;
            else
                tree[i] = index;
        }
        //查询
        N = sc.nextInt();
        sc.nextLine();
        for(int i=0;i<N;i++) {
            String Name = sc.nextLine();
            String[] name = Name.split(" ");
            int index1 = allName.indexOf(name[0]);
            int index2 = allName.indexOf(name[2]);
            if(index1!=-1 && index2!=-1) {
                if(per[index1].sex.equals(per[index2].sex)) {
                    System.out.println("Whatever");
                }
                else {
                    if(find(index1)!=find(index2) || judge(index1, index2)) {
                        System.out.println("Yes");
                    }
                    else {
                        System.out.println("No");
                    }
                }
            }
            else {
                System.out.println("NA");
            }
        }
    }
    //并查集查找
    public static int find(int i) {
        if(tree[i]!=i) {
            return find(tree[i]);
        }
        else
            return i;
    }
    public static boolean judge(int index1, int index2) {
        int ret = 1;
        while (index1 != tree[index1] && index2 != tree[index2]) {
            index1 = tree[index1];
            index2 = tree[index2];
            ++ret;
            if (ret == 5) return true;	//不在五代以内
            if (index1 == index2) return false;	//五代以内存在共同祖先
        }
        return false;
    }
}

例题2:528. 奶酪 - AcWing题库

ac代码:


import java.util.*;


public class Main {
	static int N = 1010,T;
	static int n,idx;
	static long h,r;
	static int[] p = new int[N];
    static long[] x = new long[N];
    static long[] y = new long[N];
    static long[] z = new long[N];
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		T = sc.nextInt();
		for (int i = 0;i < T;i++) {
			n = sc.nextInt();
			h = sc.nextLong();
	        r = sc.nextLong();
	        init(n); //初始化p数组,使所有点都指向自己
	        
	        for (int j = 1;j <= n;j++) {
	        	x[j] = sc.nextLong();
                y[j] = sc.nextLong();
                z[j] = sc.nextLong();
                
                if (z[j] <= r) { //和下表面相切或相交的情况
                	p[find(j)] = find(1001);
                }
                if (z[j] >= h - r) { //和上表面相切或相交的情况
                	p[find(j)] = find(1002);
                }
	        }
	        
	        for (int j = 1;j <= n;j++) {
	        	for (int k = j+1;k <= n;k++) {
	        		if(next_to(x[j], y[j], z[j], x[k], y[k], z[k], r)){
	        			p[find(j)] = find(k);
	        		}
	        	}
	        }
	        System.out.println(find(1001) == find(1002) ? "Yes" : "No");   // 判断上表面是否和下表面属于一个集合。
		}
		
	
	}
	static void init(int n) {
		for (int i = 1;i <= n;i++) {
			p[i] = i;
		}
		p[1001] = 1001; //1001表示与下表面相切或相交
		p[1002] = 1002; //1001表示与下表面相切或相交
	}
	
	static int find(int x) {
		if (p[x] != x) p[x] = find(p[x]);
		return p[x];
	}
	
	static boolean next_to(long x1, long y1, long z1, long x2, long y2, long z2, long r){

        return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2) <= 4 * r * r;
    }
}

  • 10
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值