hdu3172 字典树&&并查集

http://acm.hdu.edu.cn/showproblem.php?pid=3172
题意是  如果2个人是朋友 则他们朋友的朋友也是他们的朋友 这样就组成了一圈朋友 他们就有很多朋友了  输入 2个人的名字 为2个字符串
表示2个人是朋友  并且在 同时输出他们的朋友圈有多大    注意  人数最多为100000 很多哦
 
 
显然不能用 暴力去给字符串分配编号 太大了人 那样肯定超时
就必须要用字典树了
 
 
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<stdlib.h>
struct haha
{
 struct haha *next[52];
 int cnt;
};
struct haha *root;
struct haha *build()
{
 struct haha *p;
 int i;
 p=(struct haha *)malloc(sizeof(struct haha));
 for(i=0;i<52;i++) 
  p->next[i]=NULL;
 p->cnt=0;
 return p;
}
int cs,parent[200010],rank[200010];
int getnum(char *t)
{
 int d,i,u;
 struct haha *p;
 p=root;
 d=strlen(t);   
 for(i=0;i<d;i++)
 {    
  if(t[i]>='a'&&t[i]<='z')
   u=t[i]-'a';
  else u=t[i]-'A'+26;//前面的26个位置是给小写字母留着的 不能占用 所以加26
  if(p->next[u]==NULL)
  {
   p->next[u]=build();
   p=p->next[u];
  }
  else p=p->next[u];
 }
 if(p->cnt==0)  p->cnt=++cs;//走到串对应的终点了 这时候在串的末尾对应的节点上给其编号
 return p->cnt; //分配的编号
}
int find(int x)
{
 return x==parent[x]?x:(parent[x]=find(parent[x]));
}
void del(struct haha *p) {
    int i;
 for ( i=0; i<52; ++i) 
 {
         if (p->next[i]) del(p->next[i]);
     }
     free(p);
     p = NULL;
 }
int main()
{
 int cas,i,n,n1,n2;
 char s1[25],s2[25];
 while(scanf("%d",&cas)!=EOF)
 {
  while(cas--)
  {
   cs=0;
   scanf("%d",&n);
   for(i=0;i<=n+5;i++) 
   {
    parent[i]=i;
    rank[i]=1;
   }
   root=build();
   for(i=1;i<=n;i++)
   {
    scanf("%s %s",s1,s2);
    n1=getnum(s1);
    n2=getnum(s2);
    // printf("n1=%d n2=%d  ",n1,n2);
    n1=find(n1);
    n2=find(n2);
    
    if(n1!=n2) //
    {
     
     parent[n2]=n1;
     rank[n1]+=rank[n2];//rank内的内容为当前集合的元素个数
    }
    printf("%d\n",rank[n1]);
   }
   del(root);//删除整棵树 每次都要删除整棵树 否则会错
  }
 }
 return 0;
}

你可能感兴趣的:(hdu3172 字典树&&并查集)