zoj Information Sharing(并查集)

来源:互联网 发布:手机淘宝应用图标图片 编辑:程序博客网 时间:2024/05/09 16:51
Information Sharing

Time Limit: 3 Seconds      Memory Limit: 65536 KB

There is going to be a test in the kindergarten. Since the kids would cry if they get a low score in the test, the teacher has already told every kid some information about the test in advance.
But the kids are not satisfied with the information teacher gave. They want to get more. On the testing day, some kids arrived to the classroom early enough, and then shared his/her information with another. kids are honest, if A shares with B, B can get all the information A knows, so does A.
At first the classroom is empty. As time pass by, a kid would arrive, or share information with other. However, the teacher hides somewhere, watching everything. She wants to know how much information some kid has gotten.

Input

There are multiple cases.
The first line of each case contains an integer n, indicating there is n actions.
The following n actions contain 3 types.
1: "arrive Name m a1 a2 ..am", means the kid called Name arrives at the classroom. He has m information, their id is a1 a2 ...am.
2: "share Name1 Name2", means that the kids called Name1 and Name2 share their information. (The sharing state will keep on, that means, if A share with B, later B share with CA can also get all C's information via B. One kid may share with himself, but it doesn't mean anything.)
3: "check Name", means teacher wants to know the number of information kid called Name has got. 

n is less than 100000, and is positive. The information id is among [0,1000000].
Each Name has at most 15 characters.
There would appears at most 1000 distinct information.
Each kid carry no more than 10 information when arriving(10 is included).

Output

For every "check" statement, output a single number. If there's no check statement, don't output anything.

Sample Input

8arrive FatSheep 3 4 7 5arrive riversouther 2 4 1share FatSheep riversouthercheck FatSheeparrive delta 2 10 4check deltashare delta FatSheepcheck riversouther

Sample Output

425

Hint

check 1: FatSheep has 1 4 5 7, having all the information. So answer is 4.
check 2: delta has only 4 10 , doesn't have 1 5 7. So answer is 2
check 3: riversouther has 1 4 5 7 10, having all the information. So answer is 5


Author: LI, Chao

Contest: ZOJ Monthly, August 2012


比赛时现学的map 和set用法,然后做这道题

很显然关键点是share这一步求集合的并集怎么做

因为题目中说明了The sharing state will keep on,所以必须让share过的所有集合公用同一个集合

这正是并查集的性质!(开始没想到用并查集实现,各种wa,写到最后才发现特么就是个并查集,orz。。。)

因为是第一次用map和set,所以还是把代码贴上来吧。。。


#include <stdio.h>#include <set>#include <map>#include <string.h>#include <string>using namespace std;int fa[100005];set <int>   s[100005];map <string,int>   m;int main(){    int n,countn;    int i,j,q;    char command[20],str2[20],str3[20];    while(scanf("%d",&n) != EOF){        for(i = 0;i < 100005;i++){            fa[i] = i;            s[i].clear();        }        m.clear();        countn = 0;        while(n--){            scanf("%s",command);            if(command[0] == 'a'){                scanf("%s",str2);                m[str2] = countn;                scanf("%d",&q);                while(q--){                    int tem;                    scanf("%d",&tem);                    s[countn].insert(tem);                }                countn++;            }            else if(command[0] == 'c'){                scanf("%s",str2);                int p = m[str2];                while(fa[p] != p)                    p = fa[p];                m[str2] = p;                printf("%d\n",s[p].size());//集合的大小,即是所求的答案            }            else{                scanf("%s%s",str2,str3);                int p2 = m[str2];                int p3 = m[str3];                while(fa[p2] != p2)                    p2 = fa[p2];                while(fa[p3] != p3)                    p3 = fa[p3];                if(p2 == p3)    //这一个地方很重要,如果这两个是同一个集合,                    continue;   //就不要再进行下面的操作,否则会出错                while(!s[p2].empty()){                    int tem = *s[p2].begin();                    s[p3].insert(tem);                    //如果集合中已经存在tem,则这个插入操作是无效的                    //就是利用这条性质来求集合的并集                    s[p2].erase(tem);                }                m[str2] = p3;                m[str3] = p3;                fa[p2] = p3;            }        }    }}