如果输入元素不是简单整数,该怎么办呢?可以通过map和vector实现。而且只需要输入一次,边输入边进行并查集操作。
#include <stdio.h>
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <algorithm>
#include <iterator>
using namespace std;
void init(int *p, int n)
{
for(int i=0; i<n; i++)
p[i] = -1;
}
int Find(int x, int *pn)
{
if(pn[x]<0)
return x;
return pn[x] = Find(pn[x], pn);
}
// 合并:大的合并到小的那里
void Union(int x, int y, int *pn)
{
int h1 = Find(x, pn);
int h2 = Find(y, pn);
if(h1<h2) // 合并到小的那里
{
pn[h2] = h1;
pn[h1]--;
}
else if(h1==h2) // 同属一个等价类,则返回
{
return;
}
else
{
pn[h1] = h2;
pn[h2]--;
}
}
const int N = 10000;
// 字符串处理技巧:用一个map来接收,这样的话,可以实现string->int的查询,再将其存入vector,可以实现int->string的查询;
// 注意要include<string>,不是include<string.h>
int main()
{
//初始化并查集
int *parent = new int[N];
init(parent, N);
// 准备输入
int m, n;
cin>>m; //m 个“关系”
string str1,str2;
map<string,int>ms; // 给出字符串找index
map<string,int>::iterator msi;
vector<string>mv(m); // 给出index找字符串
int i=0,j=0;
while(i<2*m)
{
// 读入第一个字符串
cin>>str1;
if(ms.count(str1)==0 )
{
ms.insert(pair<string,int>(str1, j));
mv.insert(mv.begin()+j,str1);
j++;
}
i++;
// 读入第二个字符串
cin>>str2;
if(ms.count(str2)==0 )
{
ms.insert(pair<string,int>(str2, j));
mv.insert(mv.begin()+j,str2);
j++;
}
i++;
//
msi = ms.find(str1);
int x = msi->second;
msi = ms.find(str2);
int y = msi->second;
Union(x,y,parent);
}
cout<<"出现过的字符串:"<<endl;
copy(mv.begin(), mv.begin()+j, ostream_iterator<string>(cout, "\n"));
// k个查询请求
int k;
cin>>k;
string st;
int z;
for(z=0;z<k;z++)
{
cin>>st;
msi = ms.find(st);
if(msi==ms.end()) // 找不到该字符串
{
cout<<"cannot find"<<endl;
continue;
}
int index = msi->second;
int in = parent[index] < 0 ? index : parent[index];
cout<<st<< " -> parent= "<<mv[in]<<endl;
}
delete []parent;
return 0;
}
输入文件:
12
a0 a2
a2 a4
a1 a7
a3 a5
a4 a8
a10 a11
a0 a6
a1 a5
a0 a4
a3 a7
a2 a8
a9 a12
6
a0
a1
a4
a7
a11
xyz
表示有12个关系,6个查询请求。
根据12个关系计算字符串个数。
输出:
出现过的字符串:
a0
a2
a4
a1
a7
a3
a5
a8
a10
a11
a6
a9
a12
a0 -> parent= a0
a1 -> parent= a1
a4 -> parent= a0
a7 -> parent= a1
a11 -> parent= a10
cannot find