并查集-检查网络
【问题描述】
给定一个计算机网络以及机器间的双向连线列表,每一条连线允许两端的计算机进行直接的文件传输,其他计算机间若存在一条连通路径,也可以进行间接的文件传输。请写出程序判断:任意指定两台计算机,它们之间是否可以进行文件传输?
【输入要求】
输入若干测试数据组成。对于每一组测试,第1行包含一个整数N(≤10000),即网络中计算机的总台数,因而每台计算机可用1到N之间的一个正整数表示。接下来的几行输入格式为I C1 C2或者 C或者C C1C2或者S,其中C1和C2是两台计算机的序号,I表示在C1和C2间输入一条连线,C表示检查C1和C2间是否可以传输文件,S表示该组测试结束。当N为0时,表示全部测试结束,不要对该数据做任何处理。
【输出要求】
对每一组C开头的测试,检查C1和C2间是否可以传输文件,若可以,则在一行中输出“yes”,否则输出“no”。当读到S时,检查整个网络。若网络中任意两机器间都可以传输文件,则在一行中输出“The network is connected.”,否则输出“There are k components.”,其中k是网络中连通集的个数。两组测试数据之间请输出一空行分隔。
#include <iostream>
using namespace std;
#define MAX_N 10001
int par[MAX_N]; // 父亲
int rank[MAX_N]; // 树的高度
// 初始化n个元素
void init(int n)
{
for(int i = 1; i <= n; ++ i)
{
par[i] = i;
rank[i] = 0;
}
}
// 查询树的根
int find(int x)
{
if(par[x] == x)
return x;
else
return par[x] = find(par[x]);
}
// 合并x和y所属的集合
void unite(int x, int y)
{
x = find(x);
y = find(y);
if(x == y)
return ;
if(rank[x] > rank[y])
{
par[y] = x;
}
else
{
par[x] = y;
if(rank[x] == rank[y])
{
rank[x] ++;
}
}
}
// 判断x和y是否属于同一个集合
bool same(int x, int y)
{
return find(x) == find(y);
}
int main()
{
// num 为机器总数, m1, m2 为任意两台机器
int num, m1, m2;
// command为指令
char command;
cout << "请输入机器总数:" << endl;
while(cin >> num)
{
// 当N为0时,表示全部测试结束,不要对该数据做任何处理。
if(num == 0)
break;
if(num < 1 || num > MAX_N)
{
cout << "数据越界, 请重新输入" << endl;
continue;
}
// 并查集开始
init(num);
cout << "请输入指令:" << endl;
while(cin >> command)
{
// 错误指令的处理
if(command != 'S' && command != 'C' && command != 'I')
{
cout << "指令错误, 请重新输入" << endl;
continue;
}
// 当读到S时,检查整个网络。
// 若网络中任意两机器间都可以传输文件,则在一行中输出"The network is connected."
// 否则输出"There are k components."
if(command == 'S')
{
int count = 0;
for(int i = 1; i <= num; ++ i)
{
if(par[i] == i)
count ++;
}
if(count == 1)
{
cout << "The network is connected." << endl;
}
else
{
cout << "There are " << count << " components." << endl;
}
cout << endl;
cout << "请输入机器总数:" << endl;
break;
}
// 输入两个机器
// cout << "请输入两个机器编号:" << endl;
cin >> m1 >> m2;
// C开头的测试,检查C1和C2间是否可以传输文件
// 若可以,则在一行中输出"yes",否则输出"no"。
if(command == 'C')
{
if(same(m1, m2))
{
cout << "yes" << endl;
}
else
{
cout << "no" << endl;
}
cout << "请输入指令:" << endl;
}
// I表示在C1和C2间输入一条连线
if(command == 'I')
{
unite(m1, m2);
cout << "请输入指令:" << endl;
}
}
}
return 0;
}
/*
请输入机器总数:
3
请输入指令:
I 3 1
请输入指令:
I 2 3
请输入指令:
C 1 2
yes
请输入指令:
S
The network is connected.
请输入机器总数:
3
请输入指令:
C 1 2
no
请输入指令:
I 1 2
请输入指令:
C 1 2
yes
请输入指令:
S
There are 2 components.
*/

浙公网安备 33010602011771号