zoj3641 Information Sharing 并查集+set

本文介绍了一种使用数据结构解决模拟教学场景信息共享问题的方法。通过应用map、set及并查集等数据结构,实现了学生间信息的有效传递与查询。具体地,使用map将学生姓名映射为唯一标识符,利用set记录每个学生掌握的不同信息,采用并查集维护学生间的信息共享关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    一间教室,起初是空的,有三种命令

1: "arrive Name m a1 a2 ..am"   名字为 Name的小朋友进来了,并且携带了m条信息,分别是a1,a2...am

2: "share Name1 Name2" 名字为Name1,Name2的小朋友分享他们的信息。

3: "check Name" 检查名字为Name的同学,并输出这个同学当前了解多少条不同的信息。

用map可以把名字hash成一个值,那么对每个小朋友可以用一个set来保存,合并的时候,名字之间的关系可以考虑用并查集存储,然后把set【A】的信息全部插入到set【B】中,那么一个集合里的人所了解的信息将会是同一个set。

两个注意的地方,

1:合并的时候可以直接循环一个set里的值,将其插入到父节点对应的set里,之后把这个集合清空,否则数据太大了会MLE..

2:由于存在share Name1 Name1,或者是这两个人当前已经在同一个集合里的情况,所以这里要判断一下,如果是同一个人或者是这两个人在同一个集合里,就continue掉。否则插入的时候自己往自己里面插元素等于没插,之后再一情况就错掉了= =...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstring>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
const int maxn=201000;
int n,m,k;
int f[maxn];
string s,s1,s2,cmd;
int find(int x)
{
    if (f[x]==x) return x;
    else return f[x]=find(f[x]);
}
set<int>info[maxn];
set<int>::iterator it;
int ct;
int main()
{
//    freopen("in.txt","r",stdin);
    while(cin>>n)
    {
        memset(f,0,sizeof f);
        ct=1;
        map<string,int>hs;
        hs.clear();
        int id;
        for (int i=1; i<=n; i++)
        {
            cin>>cmd;
            if (cmd[0]=='a')
            {
                cin>>s;
                if (hs.find(s)==hs.end())
                {
                    id=ct;
                    info[id].clear();
                    f[ct]=ct;
                    hs[s]=ct++;
                }
                else id=hs[s];

                cin>>m;
                for (int i=0; i<m; i++)
                {
                    cin>>k;
                    info[id].insert(k);
                }
            }
            else if (cmd[0]=='s')
            {
                int id1,id2;
                cin>>s1>>s2;
                if (hs.find(s1)==hs.end())
                {
                    id1=-1;
                }
                else id1=hs[s1];

                if (hs.find(s2)==hs.end())
                {
                    id2=-1;
                }
                else id2=hs[s2];

                if (id1>=0 && id2>=0 && id1!=id2)
                {
                    id2=find(id2);
                    id1=find(id1);
                    if (id1==id2) continue;
                    f[id2]=id1;

                    for (it=info[id2].begin(); it!=info[id2].end(); it++)
                    {
                        info[id1].insert(*(it));
                    }
                    info[id2].clear();
                }

            }
            else if (cmd[0]=='c')
            {
                cin>>s;
                if (hs.find(s)==hs.end()) cout<<0<<endl;
                else
                {
                    id=hs[s];
                    id=find(id);
                    cout<<info[id].size()<<endl;
                }
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值