ZOJ 3641 Information Sharing

2023-12-15 18:09
文章标签 zoj information sharing 3641

本文主要是介绍ZOJ 3641 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


Author: LI, Chao
Contest: ZOJ Monthly, August 2012


大意——要考试了,老师给同学们讲了一些信息。但是同学们觉得这些不够,于是他们就相互交换意见,分享信息。现在给你n个操作,它们有3种形式:1.arrive Name m a1 a2 ... am代表名为Name的学生到达教室,他携带m个信息,分别是a1,a2,...,am。2.share Name1 Name2代表名为Name1和Name2的学生互相分享信息。3.check Name代表检查名为Name的学生当前携带的信息个数。要你对于每一个check操作都输出一个相对应的值。注意:如果A与B先分享了信息,而B与C后分享了信息,那么A也有C的信息。


思路——很显然,这是一个并查集的题。我们可以用set容器来存储学生的信息,并利用父亲集合来维护合并后的信息。开始时,我们初始化学生的父亲集合即为他自己。而在分享信息时,合并两个集合后改变它的父亲集合,并清空被改变父亲集合的集合。又因为询问的是学生名字,所以我们用map容器来映射学生所在的孩子集合。最后查找时只需找到该学生所在孩子集合的父亲集合,然后访问它的规模大小即可。


复杂度分析——时间复杂度:O(n+n*m),空间复杂度:O(n)


附上AC代码:


#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
#include <iomanip>
#include <ctime>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <deque>
//#pragma comment(linker, "/STACK:102400000, 102400000")
using namespace std;
typedef long long ll;
const double pi = acos(-1.0);
const double e = exp(1.0);
const double eps = 1e-8;
const int maxn = 100005;
set<int> mess[maxn]; // 存储学生携带的信息
map<string, int> test; // 存储学生携带的信息所在的集合
int father[maxn]; // 存储学生携带的信息所在的集合的父亲集合
char op[10], stu1[20], stu2[20]; // 分别表示选择的操作,学生1名字和学生2名字
int n; // 操作个数
short m; // 学生携带的信息个数int find(int x); // 找到x集合的父亲集合
void _union(int x, int y); // 合并两个集合int main(){ios::sync_with_stdio(false);while (~scanf("%d", &n)){for (int i=1; i<=n; i++){father[i] = i; // 初始化集合mess[i].clear(); // 清空集合里的信息}test.clear(); // 清空映射关系int cnt = 0; // 记录学生人数,也即按先后到达顺序编号while (n--){scanf("%s%s", op, stu1);if (!strcmp(op, "arrive")){scanf("%hd", &m);test[stu1] = ++cnt; // 映射关系编号int num;while (m--){scanf("%d", &num);mess[cnt].insert(num); // 该学生携带的信息放入集合}}else if (!strcmp(op, "share")){scanf("%s", stu2);_union(test[stu1], test[stu2]); // 合并学生1和学生2的信息}elseprintf("%d\n", mess[find(test[stu1])].size()); // 输出该学生所在父亲集合的信息个数}}return 0;
}int find(int x){return father[x]==x ? x : father[x]=find(father[x]); // 路径压缩
}void _union(int x, int y){x = find(x);y = find(y);if (x != y){ // 不在同一个集合,按规模大小合并if (mess[x].size() < mess[y].size()){mess[y].insert(mess[x].begin(), mess[x].end()); // y规模大,将x集合放到y集合中,并改变x的父亲集合以及清空集合x,以下类似father[x] = y; mess[x].clear();}else{mess[x].insert(mess[y].begin(), mess[y].end());father[y] = x; mess[y].clear();}}
}


这篇关于ZOJ 3641 Information Sharing的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/497377

相关文章

数论ZOJ 2562

题意:给定一个数N,求小于等于N的所有数当中,约数最多的一个数,如果存在多个这样的数,输出其中最大的一个。 分析:反素数定义:对于任何正整数x,其约数的个数记做g(x).例如g(1)=1,g(6)=4.如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数。 性质一:一个反素数的质因子必然是从2开始连续的质数。 性质二:p=2^t1*3^t2*5^t3*7

zoj 1721 判断2条线段(完全)相交

给出起点,终点,与一些障碍线段。 求起点到终点的最短路。 枚举2点的距离,然后最短路。 2点可达条件:没有线段与这2点所构成的线段(完全)相交。 const double eps = 1e-8 ;double add(double x , double y){if(fabs(x+y) < eps*(fabs(x) + fabs(y))) return 0 ;return x + y ;

zoj 4624

题目分析:有两排灯,每排n个,每个灯亮的概率为p,每个灯之间互不影响,亮了的灯不再灭,问两排中,每排有大于等于m个灯亮的概率。 设dp[ i ][ j ]为第一排亮了i个灯,第二排亮了j个灯,距离目标状态的期望天数。显然 i >= m ,j >= m时 , dp[ i ][ j ] = 0 。 状态转移 : 第一排亮了a个灯,a 在[ 0 , n - i] 之间,第二排亮了b个灯 , b 在

zoj 3228 ac自动机

给出一个字符串和若干个单词,问这些单词在字符串里面出现了多少次。单词前面为0表示这个单词可重叠出现,1为不可重叠出现。 Sample Input ab 2 0 ab 1 ab abababac 2 0 aba 1 aba abcdefghijklmnopqrstuvwxyz 3 0 abc 1 def 1 jmn Sample Output Case 1 1 1 Case 2

ZOJ Monthly, August 2014小记

最近太忙太忙,只能抽时间写几道简单题。不过我倒是明白要想水平提高不看题解是最好的了。 A  我只能死找规律了,无法证明 int a[50002][2] ;vector< vector<int> > gmax , gmin ;int main(){int n , i , j , k , cmax , cmin ;while(cin>>n){/* g

ZOJ 3324 Machine(线段树区间合并)

这道题网上很多代码是错误的,由于后台数据水,他们可以AC。 比如这组数据 10 3 p 0 9 r 0 5 r 6 9 输出应该是 0 1 1 所以有的人直接记录该区间是否被覆盖过的方法是错误的 正确方法应该是记录这段区间的最小高度(就是最接近初始位置的高度),和最小高度对应的最长左区间和右区间 开一个sum记录这段区间最小高度的块数,min_v 记录该区间最小高度 cover

计算机视觉中,什么是上下文信息(contextual information)?

在计算机视觉中,上下文信息(contextual information)是指一个像素或一个小区域周围的环境或背景信息,它帮助模型理解图像中对象的相对位置、大小、形状,以及与其他对象的关系。上下文信息在图像中提供了全局的语义和结构线索,使模型不仅依赖局部细节,而且能够考虑整个场景或图像的大局。 上下文信息的具体含义 局部与全局信息的结合: 局部信息:这是指某个小区域或某个像素点的特征。通过小

【ZOJ】3362 Beer Problem 最小费用流

传送门:【ZOJ】3362 Beer Problem 题目分析:这道题本来应该很快就AC的,但是!因为我以前犯的一个致命错误导致我这题一天了到现在才调出来!唉。。失策。。貌似给的模板也有这个错误。。。马上就去改。。但是这个错误竟然还能过掉那么多的题。。害我还要一题一题的改回去。。 本题就是赤裸裸的最小费用流。 新建汇点t(源点即1),将所有的n-1个城市和汇点建边,容量为无穷大,

【ZOJ】2332 Gems 最大流——判断满流

传送门:【ZOJ】2332 Gems 题目分析:首先我们设立源点s,汇点t,s向所有宝石建边,容量为题目中给出的,然后所有可行的转换,向两个宝石之间建无向边,容量为INF,接下来所有的宝石向自己相应的类型建边,容量INF,所有的宝石向自己相应的颜色建边,容量INF。最后,所有的类型以及颜色向汇点建边,容量为题目中给出的。最后跑一遍最大流,如果满流,说明所有的宝石都成功的限制条件下分给了男主

【ZOJ】2532 Internship 最小割——关键割边

传送门:【ZOJ】2532 Internship 题目分析:题目意思很明显,问你能否增加一条边的容量使得流量增加,就是让求关键割边。关键割边怎么求?首先按照题意建图跑一遍最小割。之后在残余网络上进行dfs,将从源点s出发能到的点标记为1,将从汇点t出发能到的点重标记为2。一条边为关键割边当且仅当它为正向边且弧头标记为1,弧尾标记为2。 PS:注意dfs的细节,s出发沿正向残余网络,t出发