We have a network of computers and a list of bi-directional connections. Each of these connections allows a file transfer from one computer to another. Is it possible to send a file from any computer on the network to any other?
Each input file contains one test case. For each test case, the first line contains N (2≤N≤10^4), the total number of computers in a network. Each computer in the network is then represented by a positive integer between 1 and N. Then in the following lines, the input is given in the format:
I c1 c2
where I stands for inputting a connection between c1 and c2; or
C c1 c2
where C stands for checking if it is possible to transfer files between c1 and c2; or
S
where S stands for stopping this case.
For each C case, print in one line the word “yes” or “no” if it is possible or impossible to transfer files between c1 and c2, respectively. At the end of each case, print in one line “The network is connected.” if there is a path between any pair of computers; or “There are k components.” where k is the number of connected components in this network.
5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
S
no
no
yes
There are 2 components.
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
no
no
yes
yes
The network is connected.
设两结点为P1,P2;I P1 P2
指p1,p2两点之间建立连接。C P1 P2
指检验P1,P2之间是否能够连通。S
代表输入结束。如果最后所有点都连通,就输出“The network is connected.”。否则,输出一共有几个部分。
#include
#include
#define MAXMISE 10000
typedef struct {
int parent;
//指连接的下一个point,根的parent<0
}Point;
Point point[MAXMISE+1];
void Connect(int p1, int p2);//连接p1,p2
int Check(int p1, int p2);//检查p1,p2是否连接
int FindRoot(int p);//找到p的根
int CountComponent(int N);//查找该森林有几棵树
void main() {
int N,p1,p2;
char symbol;
scanf("%d", &N);
getchar();
for (int i = 1; i <= N; i++) {
point[i].parent = -1;//初始化
}
scanf("%c", &symbol);
while (symbol != 'S') {
scanf("%d %d", &p1, &p2);
if (symbol == 'C') {
int res=Check(p1, p2);
if (res)
printf("yes\n");
else
printf("no\n");
}
else if (symbol == 'I'){
Connect(p1, p2);
}
getchar();
scanf("%c", &symbol);
}
int count = CountComponent(N);
if (count==1)//所有结点全部连通
printf("The network is connected.");
else //总共有几个连通部分
printf("There are %d components.", count);
}
int FindRoot(int p) {
while (point[p].parent > 0)
p = point[p].parent;
return p;
}
void Connect(int p1, int p2) {
int Root1 = FindRoot(p1);
int Root2 = FindRoot(p2);
if (Root1 != Root2) {//规模较小的依附到规模较大集合
if (point[Root2].parent < point[Root1].parent) {//Root2是较大集合
point[Root2].parent += point[Root1].parent;
point[Root1].parent = Root2;
}
else {//Root1是较大集合
point[Root1].parent += point[Root2].parent;
point[Root2].parent = Root1;
}
}
}
int Check(int p1, int p2) {
int Root1 = FindRoot(p1);
int Root2 = FindRoot(p2);
if (Root1 == Root2)
return 1;
else
return 0;
}
int CountComponent(int N) {
int count = 0;
for (int i = 1; i <= N; i++) {
if (point[i].parent < 0)
count++;
}
return count;
}
1.这个代码参考了其他博客,在此重敲一遍只是便于个人记忆。
2.“连通”指的是 I 3 2
与 I 2 3
的结果是相同的,单向考虑是不对的。
3.在合并集合时(Connect函数中),要判断哪一集合规模较大,让较小的依附至较大集合。如果不进行判断,测试点4 最大N,递增链,卡不按大小union 将运行超时,原因在于FindRoot时用时变长。