网络连接——并查集 题解

Description

Bob是一个网络管理员,负责监控计算机网络。他要维护网络内计算机之间的连接的日志。每个连接是双向的。如果两台计算机是直接连接的,或者与同一台计算机互联,则我们称这两台计算机是互联的。有的时候,需要Bob根据日志信息作出判断,确定给出的两台计算机是否直接或间接地互联。
请基于输入信息编写一个程序,回答下述问题的“是”和“否”的次数:
computeri 是否与computerj 互联? 

Input

输入包含多个测试样例。每个测试用例定义如下:
1 网络中计算机的个数(一个正整数);
2 一个列表,每句的形式如下:
(a) c computeri computerj,其中computeri 和computerj 是整数,表示计算机的编号,编号取值从1到网络中计算机的个数。这句表示computeri 和computerj是互联的。
(b) q computeri computerj,其中computeri 和computerj是整数,表示计算机的编号,编号取值从1到网络中计算机的个数。这句表示这样的问题:computeri 和computerj是互联的吗?
测试用例之间用空行分开。
列表中每句一行。句中计算机出现的次序是任意的,与语句类型无关。在语句类型 (a) 被处理以后,修改日志;对于语句类型(b),则根据当前网络设置进行处理。

输入包含多组测试样例,遇到0结束。

Output

对于所有(b)语句,有N1个回答“是”和N2个回答“否”。程序在一行中按这样的次序输出两个数字:N1, N2,如样例输出所示。在两个测试用例之间有一个空行。

Sample Input

10

c 1 5

c 2 7

q 7 1

c 3 9

q 9 6

c 2 5

q 7 5

0

Sample Output
1, 2

分析

并查集

输入‘c’时,将集合合并;输入‘q’时,查询computeri computerj父节点是否相同

但是,题目中有这么一句话:输入包含多组测试样例,遇到0结束。

测试样例是多组数据!!!

比如:

10
c 1 5
c 2 7
q 7 1
c 3 9
q 9 6
c 2 5
q 7 5
6
c 1 4
c 3 4
q 2 1
0

这就需要对基本程序做一个修改,另外,样例输出的逗号后有一个空格!

代码
#include<bits/stdc++.h>
using namespace std;
long long n;
char c;
int fa[114514];
void init(int n){
	for(int i=1;i<=n;i++){
		fa[i]=i;
	}
}
int find(int x){//查询 
	if(fa[x]==x) return x;
	else return fa[x]=find(fa[x]);
}
void merge(int x,int y){//合并 
	x=find(x);
	y=find(y);
	if(x==y) return;
	fa[x]=y;
}
char s[114514];
int ans,anss,ansf;
int main(){
	cin>>n;
	here:;//goto函数转回的指定位置 
	init(n);
	int a,b;
	
	while(1){
		if(scanf("%s",s)==-1)break;
		if(s[0]>='1'&&s[0]<='9'){//当输入的是数字,说明输入的是不同样例中的n 
			//处理n 
			cout<<anss<<", "<<ansf<<endl;//输出上一组数据的结果 
			anss=0;
			ansf=0;
			n=0;
			for(int i=0;i<strlen(s);i++) n=n*10+(s[i]-'0');//将字符转化为数字 
			goto here;//回到指定位置 
		}else if(s[0]=='q'){//输入的是字符,用c储存 
			c='q';
		}else if(s[0]=='c'){
			c='c';
		}else break;
		cin>>a>>b;
		if(c=='c'){//判断 
			merge(a,b);//合并 
		}else if(c=='q'){
			
			if(find(a)==find(b)){//判断父节点是否相同 
				anss++;
			}else{
				ansf++;
			}
		} 
	}
	
	cout<<anss<<", "<<ansf<<endl;//输出最后一组数据的结果 
	//注意逗号后有一个空格 
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值