UVA11503 Virtual Friends 题解

UVA11503 Virtual Friends 题解

题目:

原题面:

题目描述

PDF

UVA11503 Virtual Friends 题解_第1张图片

输入格式

UVA11503 Virtual Friends 题解_第2张图片

输出格式

样例
样例输入
1
3
Fred Barney
Barney Betty
Betty Wilma
样例输出
2
3
4

翻译:

T T T 组数据和 n n n 个关系,每个关系代表 A A A B B B 是朋友关系(朋友的朋友也是朋友)。每次关系表时候,都要输出 A A A B B B 所在朋友群中的人数。

算法:并查集+哈希

字符串怎么处理呢?

可以用哈希来解决,用 unordered_map 来存储每一个字符串所对应的数值。(或者手动写字符串哈希,注意要准备几个好用的大质数哦~)

(之所以不用 map ,是因为 map 的常数比较大,里面的数据都是自动排序的,而 unordered_map 不会自动排序,常数略小。)

之后就可以用并查集来做啦~。

不会并查集的同志请做 P3367

此外,还有不少细节要注意。

因为有多组数据,所以不要忘记每次循环都要初始化。初始化时,还要注意每次读入是两个人名,所以记得数组要开两倍。

不懂的同志看代码~(注释也是蛮详细的呢)

代码:

//UVA11503 Virtual Friends 题解 
#include
using namespace std;
#define ll long long
const ll N=2e5+10;//开两倍不要忘了 
ll T,n,fa[N],sz[N],tot;
string x,y;
unordered_map<string,ll> p;
void jian(){
	//注意,i<=n*2,要*2哦 
	for(int i=0;i<=n*2;i++) fa[i]=i,sz[i]=1;
	return;
}
ll getfa(ll x){
	// fa=getfa(fa[x]) 用路径压缩,节省时间复杂度 
	return fa[x]==x?x:fa[x]=getfa(fa[x]);
}
void hebing(ll x,ll y){
	ll fx=getfa(x),fy=getfa(y);
	if(fx!=fy){//若 x 和 y 本身就是朋友,不需要再合并了 
		if(sz[fx]>sz[fy]) swap(fx,fy);
		fa[fx]=fy,sz[fy]+=sz[fx];//启发式合并,合并在短的一边,优化时间复杂度 
	}
}
ll size(ll x){
	return sz[getfa(x)];
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>T;
	while(T--){
		cin>>n;
		p.clear(),tot=0,jian();//初始化 
		while(n--){
			cin>>x>>y;
			if(p.find(x)==p.end()) p[x]=++tot;//用 p 记录字符串所对应的数值 
			if(p.find(y)==p.end()) p[y]=++tot;
			hebing(p[x],p[y]);
			cout<<size(p[x])<<"\n";
		}
	}
	return 0;
}

你可能感兴趣的:(题解,c++,算法)