Friend

Friend

Time Limit:   1000MS       Memory Limit:   65535KB
Submissions:   102       Accepted:   10

 

Description

 

每个人都有朋友,朋友也有很多种,比如: 

石友--情谊坚贞的朋友。 

挚友--志同道合的朋友。

益友--于己有帮助的朋友。

网友--在互联网结识的朋友。

闺友--闺房中无话不谈的朋友。

君子交:指道义之交,即在道义上相互支持的朋友。

竹马之交:少年时骑竹马为戏的朋友,指自幼相交的朋友,等等。

现在dearway定义如果王二和张三是朋友,李四和张三也是朋友,那么王二和李四也是朋友,即朋友具有传递关系。现在给你N种朋友关系,问你有多种朋友集合,这些集合里不会出现两个朋友来自两个不同的集合。

 

 

Input

 

多组数据输入(小于等于10组)。每组数据第一行为一个整数N( 1 <= N <= 1000)表示N种朋友关系,接下来N行,每行首先输入一个整数ni( 1 <= ni <= 10)表示该种朋友关系中包含ni个人。然后ni个字符串,每个字符串由52个大小写英文字母及数字组成且长度小于10,表示ni个不同的人。 

 

 

Output

 

每组数据输出一行,表示满足要求的答案。 

 

 

Sample Input

4
2 Hilary Dearway
1 Hilary
2 Rusty Serena
2 Serena Luoxi
10
2 a b
2 b c
1 c
3 a d e
2 e f
2 f g
2 g h
2 h i
2 j k
1 z 

Sample Output

2
3

解析:
题意:问有多少个不相关的朋友圈
思路:这是一道不错的并查集问题,其中牵扯到字符串的记录,
①可以用字典树记录字符串,最后还是要返回编号,基于题目中的“每个字符串由52个大小写英文字母及数字组成且长度小于10”
②用C++中的
#include <map>
#include <sttring>
map<string,int>mymap;
将字符串转成数字,便于记录
然后其他的其实跟基本并查集一样,初始化、统一父结点,代码如下:
# include<iostream>
# include<cstring>
# define N 100005
using namespace std;
int parent[N];
int cnt;
struct node 
{
    int flag;
    int num;
    node *next[126];
    node()
    {
        memset(next,NULL,sizeof(next));
        flag=0;
    }
};
//node *root=new node;
void Init()
{
    int i;
    for(i=0;i<10005;i++)
        parent[i]=i;
}
int find(int a)
{
  if(a!=parent[a])
  {
      parent[a]=find(parent[a]);
  }
  return parent[a];
}
void Union(int s,int e)
{
    int root_s,root_e,temp;
    root_s=find(s);
    root_e=find(e);
    if(root_s<root_e)
    {
        temp=root_s;
        root_s=root_e;
        root_e=temp;
    }
    if(root_s!=root_e)
    {
        parent[root_s]=root_e;
    }
}
int Transfor(char s[],struct node *root)//这里用的是字典树来记录的
{
    int i,x;
    int len=strlen(s);
    node *p=root;
    for(i=0;i<len;i++)
    {
       x=s[i]-'0';
       if(p->next[x]==NULL)
           p->next[x]=new node;
       p=p->next[x];
    }
    if(p->flag==1)//出现过
        return p->num;
    else 
    {
        p->flag=1;
        p->num=cnt;
        cnt++;
    }
    return p->num;
}
/*void Clear()
{
    memset(root->next,NULL,sizeof(root->next));
}*/
int main()
{
    int nCase,nNum,sign,i,leap;
    char str[30];
    while(cin>>nCase)
    {
        node *root=new node;
        cnt=0;
        leap=0;
        Init();
        while(nCase--)
        {
            cin>>nNum;
            for(i=0;i<nNum;i++)
            {
                cin>>str;
                if(i==0)
                 sign=Transfor(str,root);
                 else
                 {
                     Union(sign,Transfor(str,root));//统一父结点
                 }
            }
        } 
            for(i=0;i<cnt;i++)
            {
                if(find(i)!=i)leap++;//用find(i)==i来判断,效果一样
            }
            cout<<cnt-leap<<endl;
        //    Clear();
            delete root;
    }
    return 0;
}

 

posted on 2012-08-13 18:51  即为将军  阅读(293)  评论(0)    收藏  举报

导航