并查集-检查网络
【问题描述】
给定一个计算机网络以及机器间的双向连线列表,每一条连线允许两端的计算机进行直接的文件传输,其他计算机间若存在一条连通路径,也可以进行间接的文件传输。请写出程序判断:任意指定两台计算机,它们之间是否可以进行文件传输?
【输入要求】
输入若干测试数据组成。对于每一组测试,第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. */