题目
案例4-1.7 文件传输 (25point(s))
当两台计算机双向连通的时候,文件是可以在两台机器间传输的。给定一套计算机网络,请你判断任意两台指定的计算机之间能否传输文件?
输入格式:
首先在第一行给出网络中计算机的总数 N (2≤N≤10^4 ),于是我们假设这些计算机从 1 到 N 编号。随后每行输入按以下格式给出:
I c1 c2
其中I表示在计算机c1和c2之间加入连线,使它们连通;或者是
C c1 c2
其中C表示查询计算机c1和c2之间能否传输文件;又或者是
S
这里S表示输入终止。
输出格式:
对每个C开头的查询,如果c1和c2之间可以传输文件,就在一行中输出"yes",否则输出"no"。当读到终止符时,在一行中输出"The network is connected.“如果网络中所有计算机之间都能传输文件;或者输出"There are k components.”,其中k是网络中连通集的个数。
输入样例 1:
5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
S
输出样例 1:
no
no
yes
There are 2 components.
输入样例 2:
5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
I 1 3
C 1 5
S
输出样例 2:
no
no
yes
yes
The network is connected.
代码
考查的是并查集。两台计算机连通的本质是在同一个集合。所以计算机逐渐联网的过程可以看成子集合逐渐合并的过程。
#include<iostream>
using namespace std;
#define MaxSize 10000
void Initialization(int S[], int n);
int Find(int S[], int X);
void Union(int S[], int x1, int x2);
//题目的计算机是从1开始编号的
int main() {
int n;
int set[MaxSize];//定义集合,集合的编号就代表了元素。
char in;
cin >> n;
Initialization(set, n);
cin >> in;
while (in != 'S') {
int x, y;
cin >> x >> y;
if (in == 'I') {
Union(set, x-1, y-1);
} else if (in == 'C') {
int root1 = Find(set, x-1); //题目的计算机从1开始编号
int root2 = Find(set, y-1);
if (root1 == root2)
cout << "yes" << endl;
else
cout << "no" << endl;
}
cin >> in;
}
//此时,in=='S'
int count = 0;
for (int i = 0; i < n; i++) {
if (set[i] < 0)
count++;
}
if (count == 1)
cout << "The network is connected." << endl;
else
cout << "There are " << count << " components." << endl;
return 0;
}
void Initialization(int S[], int n) { //初始化,都没有连通
for (int i = 0; i < n; i++)
S[i] = -1;
}
int Find(int S[], int X) { //默认是找得到的
while (S[X]>=0) {
X = S[X]; //不断往上走
}
return X;
}
void Union(int S[], int x1, int x2) {
int root1 = Find(S, x1);
int root2 = Find(S, x2);
if (S[root1] < S[root2]) { //说明root1大
S[root1] += S[root2];
S[root2] = root1;
} else {
S[root2] += S[root1];
S[root1] = root2;
}
}