并查集, 这道题默认情况下是 0 号学生是感染者。所以查找是只要查找跟 0 号学生在同一根结点下就行了。
package poj;
import java.util.Scanner;
public class Poj1611_20120814_0 {
private static int [] set = new int[30001];
private static int [] rank = new int[30001];
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int n, m, i,j, count, temp;
while(true){
n = in.nextInt();
m = in.nextInt();
makeSet(n);
if((m|n)==0){
break;
}
for(i = 0; i < m; ++i){
count = in.nextInt();
if(count==0){
continue;
}
temp = in.nextInt();
for(j = 1; j < count; ++j){
union(temp, in.nextInt());
}
}
System.out.println(count(n));
}
}
private static int count(int n){
int i,res = 0;
for(i = 0; i < n; ++i){
if(findx(i) == findx(0)){ //查找时查找与 0 号学生在同一根结点下,即为受感染者。
++res;
}
}
return res;
}
private static void makeSet(int n){
for(int i = 0; i < n; ++i){
set[i] = i;
rank[i] = 0;
}
}
private static void union(int x, int y){
x = findx(x);
y = findx(y);
if(rank[x] == rank[y]){
set[y] = x;
++rank[x];
}else{
if(rank[x]>rank[y]){
set[y] = x;
}else{
set[x] = y;
}
}
}
private static int findx(int x){
if(x!=set[x]){
set[x] = findx(set[x]);
}
return set[x];
}
}