Information Sharing

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3641

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 C, A 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

8
arrive FatSheep 3 4 7 5
arrive riversouther 2 4 1
share FatSheep riversouther
check FatSheep
arrive delta 2 10 4
check delta
share delta FatSheep
check riversouther

Sample Output

4
2
5

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

题意:幼儿园小朋友即将要考试,老师为了避免大家考不好提前告诉学生部分题目的答案,每位同学只知道一部分答案,但是他们能够分享,分享满足如下规则A与B分享,B再与C分享,那么C也会知道A知道的,A也会知道C知道的。老师很想知道通过学生一些信息共享后某些同学知道的总题数。

解题思路: 这是一题并差集题目。
1)这题难点在合并两个kid,还得把两个kid携带的几个信息合并,当然重复的不算。
2)这很显然得用set,set的insert方法不插入重复元素。3)kid的区别体现在名字上,这个名字是个字符串,而并查集使用int型搞的,那么应该能想起键值对,就是map。4)还有一个要注意的是合并kid携带信息时候要把小的合并到大的,要不然就内存就超了。
5)或者合并一个以后就把没用的clear了。结合起来更好。

复杂度分析: 时间复杂度:o(n)
空间复杂度:o(n)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<map>
#include<set>
using namespace std;
const int maxn=100005;
set<int> s[maxn];
map<string,int> m1;
int father[maxn];
char op[21],na[21],nb[21];

int find(int x)
{
    if(x==father[x]) return x;
    return father[x]=find(father[x]);
}

void unite(int x,int y)
{
    int fx=find(x);
    int fy=find(y);
    if(fx != fy)
    {
        if(s[fx].size() < s[fy].size())
        {
            s[father[fx]=fy].insert(s[fx].begin(),s[fx].end());

        }
        else{
            s[father[fy]=fx].insert(s[fy].begin(),s[fy].end());

        }
    }
}
int main()
{
    int n,m,cnt,c;
    while(scanf("%d",&n) !=EOF)
    {
        for(int i=1;i<maxn;i++)
        {
            father[i]=i;
            s[i].clear();
        }
        m1.clear();
        cnt = 0;
        while(n--)
        {
            scanf("%s",op);
            if(strcmp("arrive",op)==0)
            {
                scanf("%s%d",na,&m);
                m1[na]=++cnt;
                while(m--)
                {
                    scanf("%d",&c);
                    s[cnt].insert(c);
                }
            }
            else if(strcmp("share",op)==0)
            {
                scanf("%s%s",na,nb);
                unite(m1[na],m1[nb]);
            }
            else
            {
                scanf("%s",na);
                printf("%d\n",s[find(m1[na])].size());
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值