• 并查集-检查网络


    【问题描述】

    给定一个计算机网络以及机器间的双向连线列表,每一条连线允许两端的计算机进行直接的文件传输,其他计算机间若存在一条连通路径,也可以进行间接的文件传输。请写出程序判断:任意指定两台计算机,它们之间是否可以进行文件传输?

    【输入要求】

    输入若干测试数据组成。对于每一组测试,第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.
    */
    

      

  • 相关阅读:
    本地安全策略
    windows本地用户及组的区别
    mysql基本命令总结
    常用DOS命令
    AES加密算法详解
    ctf密码学习题总结
    CTF最简单的Web题
    python进阶篇
    JNI开发流程
    JDK中的Timer和TimerTask详解
  • 原文地址:https://www.cnblogs.com/mjn1/p/10893570.html
Copyright © 2020-2023  润新知