资源限制
时间限制:2.0s 内存限制:256.0MB
问题描述
w星球的一个种植园,被分成 m * n 个小格子(东西方向m行,南北方向n列)。每个格子里种了一株合根植物。
这种植物有个特点,它的根可能会沿着南北或东西方向伸展,从而与另一个格子的植物合成为一体。
如果我们告诉你哪些小格子间出现了连根现象,你能说出这个园中一共有多少株合根植物吗?
输入格式
第一行,两个整数m,n,用空格分开,表示格子的行数、列数(1<m,n<1000)。
接下来一行,一个整数k,表示下面还有k行数据(0<k<100000)
接下来k行,第行两个整数a,b,表示编号为a的小格子和编号为b的小格子合根了。
格子的编号一行一行,从上到下,从左到右编号。
比如:5 * 4 的小格子,编号:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
17 18 19 20
样例输入
5 4
16
2 3
1 5
5 9
4 8
7 8
9 10
10 11
11 12
10 14
12 16
14 18
17 18
15 19
19 20
9 13
13 17
样例输出
5
样例说明
其合根情况参考下图
思路:根据题意,输入的数字两两连接,采用并查集,直接套并查集模板。
import java.util.Scanner;
public class 历届试题合根植物 {
/**
* @param args
*/
static int pre[]=new int[1000*1001];
static int total=0; //答案,计集合的个数
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
int m,n;
m=sc.nextInt();
n=sc.nextInt();
for(int i=1;i<=m*n;i++) //m*n为并查集的所有元素
pre[i]=i;
}
int t; //初始化有t对输入
t=sc.nextInt();
total=m*n; //当前存在集合数(一个元素一个集合)
int st,en; //输入两个有联系的数
for(int j=0;j<t;j++){
st=sc.nextInt();
en=sc.nextInt();
joint(st,en); //合并为同一个集
}
//答案输出
System.out.print(total);
}
static int unionSearch(int root){
int par,tmp;
par=root;
while(root != pre[root])
root=pre[root];
while(par!=root){ //循环路径压缩
tmp=pre[par];
pre[par]=root;
par=tmp;
}
return root;
}
static void joint(int start,int end){
int root1=unionSearch(start);
int root2=unionSearch(end);
if(root1!=root2){
pre[root1]=root2;
--total;
}
}
}