有n台计算机,编号为1到n。设定如果计算机a和计算机b可以通信,则计算机b和计算机a亦可以通信;如果计算机a和计算机b可以相互通信,计算机b和计算机c可以相互通信,则计算机a和计算机c亦可以相互通信。现给定某些计算机的可通信情况,请编写程序判断任意两台计算机是否可以通信。
输入格式:
输入第一行为三个整数,n、m和q。n为计算机台数;m为输入的可通信计算机的对数;q为查询数。接下来m行,每行2个整数a和b,表示计算机a和计算机b可以互相通信。接下来q行,每行2个整数c和d,即查询计算机c和d是否可以通信。每行输入的整数以空格间隔,n、m、q均不超过1000。
输出格式:
输出为q行,即对应于输入的q个查询的结果,如果可以通信,则输出1,否则输出0。
输入样例:
3 2 1
1 2
2 3
1 3
输出样例:
1
其实这题就是并查集欸,只要会基本的使用并查集就可以写啦!!!
并查集主要代码思路:
初始化:每个点的父节点(为自己)及其深度(为1)
按秩合并:降低高度,增加宽度(加快遍历速度),即选择深度大的作为父节点,但深度一样时随便定义一个为父节点(其深度要加一)
查找:(路径压缩)查询的过程中,把沿途的每个节点的父节点都设为根节点
最后就直接查找判断要找的两个是否相通就可以啦!!!
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define MAXN 6000
int f[MAXN], hight[MAXN];
void init(int n) {//初始化
for (int i = 1; i <= n; ++i) {
f[i] = i;//父节点为自己
hight[i] = 1;//节点i的深度设为1
}
}
int find(int x){//查找父节点(路径压缩)
//查询的过程中,把沿途的每个节点的父节点都设为根节点
return x == f[x] ? x : (f[x] = find(f[x]));
}
void hebing(int i, int j) {//按秩合并
//降低高度,增加宽度(加快遍历速度)
int x = find(i), y = find(j);
if (hight[x] <= hight[y])f[x] = y;
else f[y] = x;
if (hight[x] == hight[y] && x != y)
hight[y]++;//深度相同时,将y设为x的父节点,则y树深度加一
}
int main()
{
int n, m, num, x, y;
cin >> n >> m >> num;
init(n);
for (int i = 0; i < m; ++i){
cin >> x >> y;
hebing(x, y);
}
for (int i = 0; i < num; ++i){
cin >> x >> y;
printf("%d\n", find(x) == find(y) ? 1 : 0);
}
return 0;
}