DongDong认亲戚
DongDong每年过春节都要回到老家探亲,然而DongDong记性并不好,没法想起谁是谁的亲戚(定义:若A和B是亲戚,B和C是亲戚,那么A和C也是亲戚),她只好求助于会编程的你了。
输入描述:
第一行给定n,m表示有n个人,m次操作
第二行给出n个字符串,表示n个人的名字分别是什么(如果出现多个人名字相同,则视为同一个人)(保证姓名是小写字符串)
接下来m行,每行输入一个数opt,两个字符串x,y
当opt=1时,表示x,y是亲戚
当opt=2时,表示询问x,y是否是亲戚,若是输出1,不是输出0
数据范围:1<=n,m<=20000,名字字符长度小等于10
输出描述:
对于每个2操作给予回答
示例1
输入
4 4
chen lin yi cheng
2 chen lin
1 chen lin
1 yi lin
2 yi lin
输出
0
1
ps:一看就是并查集模板题,但不同的是,一般的并查集题都是具体的数字进行并查操作,而这道题是用字符串进行操作,很容易想到把每个字符串当成某个确定的数字,再进行操作,然后果断一个TLE教做人,后来我又想到用set来存,发现还是同样的问题没解决,最后才知道可以用map来存名字,map就是一种映射关系,就可以把字符串模拟成数组(很像JavaScript里面的自定义数组)那种,进行并与查的操作,具体看代码。
我的垃圾 代码
#include<bits/stdc++.h>
using namespace std;
unordered_map<string, string> root; //存放每个人,以及对应的祖先,其跟map的区别是可以存相同的键,用法都大致相同
string GetRoot(string node){ //找祖先
if (node == root[node])
return node;
return root[node] = GetRoot(root[node]);
}
void Union(string person1, string person2){//将两人合并为亲戚
string p1 = GetRoot(person1);
string p2 = GetRoot(person2);
root[p2] = p1;
}
bool SameRoot(string person1, string person2){//查找是否是亲戚
string p1 = GetRoot(person1);
string p2 = GetRoot(person2);
return p1 == p2;
}
int main(){
int n,op,m;
string person1, person2;
cin >> n>>m;
for(int i=0;i<n;i++){
cin>>person1;
root[person1]=person1;
}
while (m--){
cin>>op>>person1>>person2;
if (op ==1 ){
Union(person1, person2);
}
else{
if (SameRoot(person1, person2))
printf("1\n");
else
printf("0\n");
}
}
return 0;
}
神仙的代码,orz,这也太nb了,菜鸡已经看呆了
#include<bits/stdc++.h>
using namespace std;
unordered_map<string,string>M;
string t,tt;
int n,m,o,i;
string find(string x){
return x==M[x]?x:M[x]=find(M[x]);
}
int main()
{
cin>>n>>m;
for(i=0;i<n;i++)
cin>>t,M[t]=t;
for(i=0;i<m;i++)
cin>>o>>t>>tt,o==1?(M[find(tt)]=find(t),0):(puts(find(t)==find(tt)?"1":"0"));
}