POJ 1611 - The Suspects - Union-Find
POJ 1611 - The Suspects
描述
严重急性呼吸系统综合症(SARS)是一种病因不明的非典型肺炎,在2003年3月中旬被确认为全球性威胁。
为了尽量减少对他人的传播,最好的策略是将疑似者与其他人分开。
在不传播疾病的大学(NSYSU)中,有很多学生群体。同一组的学生经常互相交流,一个学生可以加入几个组。
为了防止非典型肺炎的传播,NSYSU收集了所有学生团体的成员名单,并在其标准操作程序(SOP)中制定了以下规则:
一旦一个小组的成员是疑似者,这个小组的所有成员都是疑似者。
然而,他们发现,当一个学生被认定为疑似者时,要找出所有的疑似者并不容易。你的工作是写一个程序找出所有疑似者。
输入
输入文件包含几个案例。每个测试用例从一行中的两个整数n和m开始,其中n是学生数,m是组数。
你可以假设0<n<=30000和0<=m<=500。每个学生都用一个介于0和n−1之间的唯一整数来编号,最初学生0被认为是所有案件的疑似者。
这一行后面是m个组的成员列表,每个组一行。每一行都以一个整数k开始,表示组中的成员数。在成员数之后,有k个整数代表这个组中的学生。
一行中的所有整数至少用一个空格隔开。
n=0且m=0的case表示输入结束,不需要处理。
输出
对于每个案例,输出一行中的疑似者数量。
思路: 并查集
1:一个组内只要有人疑似,就整组疑似,所以同组的合并;
2:用数组记录疑似个数,合并的时候,个数累加;
3:合并时小点往大点上合并,所以大点的个数包含所有子节点的个数;
4:只为0号已被认为是疑似者,所以要求所有涉及0的点的个;
5:由于从小到大合并,同组内,最大节点就是0的根节点,且该点个数包含此组所有人数,该根节点再往上找,可找到它所涉及的所有点的根节点,此点的个数,即为最终答案;
6:find(0)是从0开始一层层找到根节点,即最大的节点,suspectCnt[find(0)]是最大点的个数,即为所有疑似者个数
package basic_data_structure;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
/**
* @author XA-GDD
*
** 思路: 并查集,
* 1:一个组内只要有人疑似,就整组疑似,所以同组的合并;
* 2:用数组记录疑似个数,合并的时候,个数累加;
* 3:合并时小点往大点上合并,所以大点的个数包含所有子节点的个数;
* 4:只为0号已被认为是疑似者,所以要求所有涉及0的点的个;
* 5:由于从小到大合并,同组内,最大节点就是0的根节点,且该点个数包含此组所有人数,该根节点再往上找,可找到它所涉及的所有点的根节点,此点的个数,即为最终答案;
* 6:find(0)是从0开始一层层找到根节点,即最大的节点,suspectCnt[find(0)]是最大点的个数,即为所有疑似者个数
*
*/
public class D_TheSuspects {
static int N,M,K;
static int _Max_Size = 30005;
static int [] parent = new int[_Max_Size];;
static int [] suspectCnt = new int[_Max_Size];;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
StringTokenizer st;
while((str = br.readLine()) != null) {
st = new StringTokenizer(str);
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
if(N==0 && M==0) break;
for(int i=0;i<N;i++) {
parent[i] = i;
suspectCnt[i] = 1;
}
for(int i=0;i<M;i++) {
st = new StringTokenizer(br.readLine());
K = Integer.parseInt(st.nextToken());
int firstNo = Integer.parseInt(st.nextToken());
for(int j=1;j<K;j++) {
int nextNo = Integer.parseInt(st.nextToken());
union(firstNo,nextNo);
}
}
System.out.println(suspectCnt[find(0)]);
}
}
static void union(int a, int b) {
int pa = find(a);
int pb = find(b);
if(pa==pb) return;
if(pa>pb) {
parent[pb] = pa;
suspectCnt[pa] += suspectCnt[pb];
}else{
parent[pa] = pb;
suspectCnt[pb] += suspectCnt[pa];
}
}
static int find(int n) {
if(parent[n]==n) return n;
return parent[n] = find(parent[n]);
}
}
浙公网安备 33010602011771号