此题并查集加字典树,普通存储字符串会导致TLE。题目大意:你来调查每个人网络社交的规模,每给你两个人的名字,代表这两个人刚刚通过网络社交成为好友,就请你算出他们刚刚成为好友的新朋友圈有多少人。(根据朋友的朋友就是我的朋友这个规则,并且最开始每个人的朋友圈人数都为1(包括自己))
我的解题思路:因为涉及到大量字符串,因此名字使用字典树来存储,使用并查集来算新朋友圈的人数。因为名字并没有事先有编号,所以我们要自己把这些名字一个个编号,这样再使用并查集就方便多了,另外再开一个存储当前节点为根节点时的集合元素个数的数组,这样每次合并操作后把元素个数也合并然后再输出答案就行了。
注意:如果给出的两个人名已经是朋友关系的话,我们无须合并,直接输出这个朋友圈的人数就可以了。
下面是我的解题代码:并查集加动态字典树
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <stack>
using namespace std;
#define N 100009
#define M 22
struct dt //定义字典树结构体
{
dt *chid[52];
int id; //当前字符串为人名的编号
dt()
{
memset(chid, 0, sizeof(chid));
id = -1;
}
};
int bleg[N]; //存储根节点
int rela[N]; //存储当前节点为根节点时的集合元素个数
char a[M], b[M];
int t, n;
int pn; //所有已知人名的总数
dt *root;
void Init(); //初始化
int Find(int x); //查找根节点
void Union(int x, int y); //合并集合
void Delete(dt *p); //删除字典树
int Insert(char str[]); //将当前人名插入字典树,返回该人名的编号
int GetID(char ch); //获得当前字符的对应下标
int main()
{
while (~scanf("%d", &t)) //这个地方有点坑,如果写成scanf("%d", &t);就会WA
{
while (t--)
{
Init();
scanf("%d", &n);
while (n--)
{
scanf("%s %s", a, b);
Union(Insert(a), Insert(b));
}
}
}
return 0;
}
void Init()
{
int i;
for (i=0; i<N; ++i) rela[i] = 1;
pn = 0;
Delete(root);
root = new dt;
return;
}
int Find(int x)
{
int z, y = bleg[x];
while (y != bleg[y])
{
y = bleg[y];
}
while (x != bleg[x])
{
z = bleg[x];
bleg[x] = y;
x = z;
}
return y;
}
void Union(int x, int y)
{
int fx = Find(x);
int fy = Find(y);
if (fx == fy) //已经是同一个朋友圈,不需要合并了
{
printf("%d\n", rela[fx]);
return;
}
bleg[fx] = fy;
rela[fy] += rela[fx];
printf("%d\n", rela[fy]);
return;
}
int Insert(char str[])
{
int i;
int strn = strlen(str);
int chnum;
dt *next = root;
for (i=0; i<strn; ++i)
{
chnum = GetID(str[i]);
if (next->chid[chnum] == NULL)
{
next->chid[chnum] = new dt;
}
next = next->chid[chnum];
}
if (next->id != -1) return next->id; //已经存储过该人名,直接返回编号
next->id = pn++;
bleg[next->id] = next->id;
return next->id;
}
void Delete(dt *p)
{
int i;
if (p == NULL) return;
for (i=0; i<52; ++i)
{
if (p->chid[i] != NULL)
{
Delete(p->chid[i]);
}
}
delete p;
return;
}
int GetID(char ch)
{
if (ch >= 'a' && ch <= 'z')
{
return ch - 'a';
}
return ch - 'A' + 26;
}