经典的并查集算法
输入
每个测试点(输入文件)有且仅有一组测试数据。
每组测试数据的第1行为一个整数N,表示黑叔叔总共进行的操作次数。
每组测试数据的第2~N+1行,每行分别描述黑叔叔的一次操作,其中第i+1行为一个整数op_i和两个由大小写字母组成的字符串Name1_i, Name2_i,其中op_i只可能为0或1,当op_i=0时,表示黑叔叔判定Name1_i和Name2_i是同一阵营的,当op_i=1时,表示黑叔叔希望知道Name1_i和Name2_i是否为同一阵营的。
对于100%的数据,满足N<=10^5, 且数据中所有涉及的人物中不存在两个名字相同的人(即姓名唯一的确定了一个人),对于所有的i,满足Name1_i和Name2_i是不同的两个人。
输出
对于每组测试数据,对于黑叔叔每次op_i=1的操作,输出一行,表示查询的结果:如果根据已知信息(即这次操作之前的所有op_i=0的操作),可以判定询问中的两个人是同一阵营的,则输出yes,否则输出no。
AC代码:
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<map>
using namespace std;
#define SIZE 100005
int isunion[SIZE];
map<string, int> a2i;
int N;
int op;
string name1, name2;
int find(int idx) {
if (!isunion[idx] || isunion[idx] == idx) {
return idx;
} else {
isunion[idx] = find(isunion[idx]);
return isunion[idx];
}
}
void merge (int idx1, int idx2) {
isunion[find(idx1)] = find(idx2);
}
bool check (int idx1, int idx2) {
return find(idx1) == find(idx2);
}
int main (int args, char* argv[])
{
memset(isunion, 0, sizeof(isunion));
//freopen("F:/in.txt","r",stdin);
int temp = 0;
cin >> N;
while(N--) {
cin >> op >> name1 >> name2;
int idx1 = a2i[name1];
int idx2 = a2i[name2];
if (!idx1)
idx1 = a2i[name1] = ++temp;
if (!idx2)
idx2 = a2i[name2] = ++temp;
if (op == 0)
merge(idx1, idx2);
if(op == 1)
cout << (check(idx1, idx2) ? "yes" : "no") << endl;
}
//fclose(stdin);
return 0;
}