Hduoj3172【字典树+并查集】

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
int f[200010], n, idnum, sum[200010];
struct tree
{
    int id;
    tree *next[52];
}root;
int finds(char *s)
{
    tree *p = &root, *q;
    int i, j, k, l, id1;
    l = strlen(s);
    for(i = 0; i < l; ++i)
    {
        if(s[i] >= 65 && s[i] <= 90)
            id1 = s[i] - 65;
        else
            id1 = s[i] - 97 + 26;
        if(p->next[id1] == NULL)
        {
            q = (tree *)malloc(sizeof(root));
            for(j = 0; j < 52; ++j)
            q->next[j] = NULL;
            q->id = 0;
            p->next[id1] = q;
            p = q;
        }
        else
        p = p->next[id1];
    }
    if(p->id == 0)
    p->id = ++idnum;
    return p->id;
}
int find(int x)
{
    if(x != f[x])
    f[x] = find(f[x]);
    return f[x];
}
int main()
{
    int i, j, k, t;
    while(scanf("%d", &t) != EOF)
    {
        for(i = 0; i < t; ++i)
        {
            scanf("%d", &n);
            for(i = 1; i <= 2*n; ++i)
            {
                f[i] = i;
                sum[i] = 1;
            }
            idnum = 0;
            for(i = 0; i < 52; ++i)
            root.next[i] = NULL;
            for(j = 0; j < n; ++j)
            {
                char s1[22], s2[22];
                scanf("%s%s", s1, s2);
                int id1 = finds(s1), id2 = finds(s2);
                int x = find(id1);
                int y = find(id2);
                if(x != y)
                {
                    f[x] = y;
                    sum[y] += sum[x];
                }
                printf("%d\n", sum[y]);
            }
        }
    }
    return 0;
}


题意:给出n个人的社交网络,每当2个人认识成为朋友的时候,就要输出这2个人所构成的社交网络的总人数。

思路:这里首先是用字典树对每个人的名字进行编号,其次就是当2个人成为朋友的时候即对他们进行合并操作,这里有个小技巧就是对于每个编号,或者说对于每个父节点用一个数组进行统计,每当2个人合并时,若不在一个集合里,则进行合并,并且将人数sum这个数组进行更新,即将新的父节点的总人数加上刚合并的那棵树的人数,若在一个集合里则不用更新直接找到父节点。每次输出当前父节点的sum数组即可。

你可能感兴趣的:(Hduoj3172【字典树+并查集】)