您的位置:首页 > 编程语言 > Java开发

利用java类的思想和并查集的方法解决同一道算法题

2015-11-13 12:58 483 查看
这里是根据一个具体算法题来说明的,java类思想去和并查集方法,是两种不同的解题思路,它们各自有优点和缺点,只是根据使用者的个人习惯。本文会将两种解题方法都写一下,感兴趣的可以看一下。
Description
2013年春天的H7N9不亚于2003年的SARS,有上百人感染、几十人死亡。为减少传播,最好的策略是与感染者隔离。
在某个城市中,有一些社团。同一社团的人常彼此交往,一个人也可能参加不同的社团。为防止H7N9可能的传播,城市的疾病卫生防治中心列出了所有这些社团的成员,并作出如下隔离措施:
一旦一个社团的某个成员是H7N9病毒携带者(或怀疑对象),该社团的所有成员都是怀疑对象。
但是,他们发现,当一个人被确定是怀疑对象时确定所有怀疑对象是不容易的。你的任务是确定所有怀疑对象。
Input
输入有多种情况。
每种情况以一行上两个整数n、m开始,其中n是所有人数,m是社团数。可假定0 < n <= 3000、0 <= m <= 100。每个人有0到n-1的唯一一个标号,编号为0的人是怀疑对象。
接着有m行,每行是一个社团的信息。该行的第一个数是整数k,接着有k个整数表示该社团的k个人。所有整数之间有空格隔开。
当输入为n = 0、m = 0时表示输入结束,这种情况不必处理。两组数据之间有一个空行。
Output
对每种情况,一行输出所有被怀疑的人员的总是。
Sample Input
100 4

2 1 2

5 10 13 11 1214

2 0 1

2 99 2

Sample Output
4

解决这个算法题,一般用并查集的思想去解决。下面给出了利用java类的思想和java集合类的方法去解决这道算法题。

package com.homework;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

/**
* 定义社团成员对象
* @author Administrator
*
*/
class Number{
List list = new ArrayList();//存放成员所参加过的社团编号
int id;//社员编号
}

public class H7N9 {
private static Scanner scanner;
private static int n;//共有n个人员
private static int m;//有m个社团
private static int num;
private static Set set;
public static void main(String[] args) {
scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();

while(n!=0||m!=0){

Number [] numbers = new Number
;

for(int i=0;i<m;i++){

int num=scanner.nextInt();

for(int j=0;j<num;j++){
int x=scanner.nextInt();
if(numbers[x]==null){
Number number = new Number();
number.list.add(i);
number.id = x;
numbers[x] = number;
}else{
numbers[x].list.add(i);
}
}
}

set = new TreeSet();
for(int i=0;i<numbers[0].list.size();i++){
set.add(numbers[0].list.get(i));
num++;
}

for(int t=1;t<numbers.length;t++){
if(numbers[t]!=null)
for(int j=0;j<numbers[t].list.size();j++)
if(set.contains(numbers[t].list.get(j))){
num++;
for(int i=0;i<numbers[t].list.size();i++)
set.add(numbers[t].list.get(i));
break;
}
}
//输出结果
System.out.println(num);
//初始化num准备进入下一次循环
num=0;
n = scanner.nextInt();
m = scanner.nextInt();
}

}
}
下面是用并查集的方法解决该问题
package com.homework;

import java.util.Scanner;

public class H7N92 {
private static Scanner scanner;
private static int n;//输入的人数
private static int m;//社团数目
private static int[] array = new int[3000];
public static void main(String[] args) {
scanner = new Scanner(System.in);
while(scanner.hasNext()){
n = scanner.nextInt();
int[] num = new int
;//用于存放以该节点为父节点的集合中元素个数,初始都为1
for(int i=0;i<n;i++){
array[i] = -1;
num[i] = 1;
}
m = scanner.nextInt();

for(int i=0;i<m;i++){
int[] number = new int[scanner.nextInt()];//每输入一组社团成员,定义一个临时数组存放
for(int j=0;j<number.length;j++){
number[j] = scanner.nextInt();
}
//该for循环就是将这一个社团的人员并到同一个集合中去(这里有一个缺陷,就是每次输入的社团人数必须大于1个,由于时间问题暂时未优化)
for(int j=1;j<number.length;j++){
int x = root(number[0]);
int y = root(number[j]);
if(x!=y){
array[y] = x;
num[x]+=num[y];
}
}
}
System.out.println(num[root(0)]);
}
}
//并查集的核心思想
public static int root(int x){
if(array[x]==-1)
return x;
else{
int temp = root(array[x]);
array[x] = temp;
return temp;
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: