题目描述
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?
Input Specification:
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.
Output Specification:
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.
Sample Input 1:
5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
S
Sample Output 1:
no
no
yes
There are 2 components.
Sample Input 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
Sample Output 2:
no
no
yes
yes
The network is connected.
解答
知识点:
并查集
路径压缩
题意:
给定N 即1-N个数
I 将两个端点连接
C 检查两个端点是否能够互通
思路:
利用简单并查集
这道题按照给定的N 构造1-N个数
利用数组set[]的下标表示1-N
数组set[]存储的是该数的根节点
初始化set[]的都为-1(表示每个点都是根节点)
进行I操作时 合并集合 通过比较集合的规模 小的集合合并到大的集合上
进行C操作时 检查根节点是否相同 相同即为一个集合
#include<iostream>
using namespace std;
/*
set[]如果是根节点则存的是该树的规模的负数值
否则存的是该节点的根节点
*/
int set[10001];
/*
路径压缩:
先找到该点的根节点
将elem指向根节点
再返回根
*/
int findRoot(int *set,int elem)
{
if(set[elem]<0) return elem;
else return set[elem]=findRoot(set,set[elem]);
}
/*
按照规模合并
*/
void Union(int *set,int Root1,int Root2)
{
if(set[Root2]<set[Root1]){//Root2的规模大于Root1
set[Root2]+=set[Root1];//Root2的规模再加上Root1的规模
set[Root1]=Root2;//将Root1的父亲节点设为Root2
}else{
set[Root1]+=set[Root2];
set[Root2]=Root1;
}
}
int main()
{
int N,A,B;
cin>>N;
//从下标为1开始存 初始值都是规模为1的根节点
for(int i=1;i<N+1;i++){
set[i]=-1;
}
char Op;
cin>>Op;
while(Op!='S'){
if(Op=='C'){
cin>>A>>B;
if(findRoot(set,A)==findRoot(set,B)) cout<<"yes"<<endl;//两个点的根节点相同 即为一个集合
else cout<<"no"<<endl;
}
else if(Op=='I'){
cin>>A>>B;
Union(set,findRoot(set,A),findRoot(set,B));
}
cin>>Op;
}
int count=0;
//此时set集合将每个点都按照输入 以集合的形式存储
for(int i=1;i<N+1;i++){
if(set[i]<0) count++;//记录集合中的根节点 根节点都是<0
}
if(count==1){
cout<<"The network is connected."<<endl;
}else cout<<"There are "<<count<<" components."<<endl;
return 0;
}