南华大学第十五届ACM程序设计竞赛(重现赛)—复读机(并查集)

链接:https://ac.nowcoder.com/acm/contest/699/B

题目描述
在某华大学里有一个无聊的群组,群内的所有成员都是复读机,他们疯狂复读着别人的消息。然而复读机们在群内也是有阵营的,一个阵营的复读机会根据心情选择是否复读同一个阵营的成员的消息,但绝对不会去复读其他阵营的消息。

群内有n个人(标号1-n号)。现在群内聊天记录中一共有m条消息。请根据这些消息,判断出如果群内第i号成员(1<=i<=n)发一条十分有趣的消息,在同一阵营的成员都会去复读这条消息情况下,那么这条消息会被复读几次?

如果无法判断i号成员和j号成员是否为同一阵营,则视为不同阵营。

输入描述:
输入包括m+1行。第一行包括两个整数n,m;其后的m行为当前的聊天记录,每行包括一个数字i和一个字符串s(表示i发了一条消息)。(保证1<=i<=n,m<=100000,消息的字符串总长不超过100000)
输出描述:
输出一行,包括n个数字。第i个数字表示第i号成员的有趣消息会被复读几次(1<=i<=n)。数字与数字之间用一个空格分隔。
示例1
输入
复制
3 5
1 a
2 a
1 b
2 c
3 c
输出
复制
2 2 2
说明
对于样例1: 由聊天记录的前两行可以得出2号和1号为同一阵营,由最后两行可得3号和2号为同一阵营,所以三者为同一阵营,他们三个发送的消息会被复读2次,故输出为2 2 2;
示例2
输入
复制
3 3
1 a
2 b
3 c
输出
复制
0 0 0
说明
对于样例2:1,2,3号无法判断是否为同一阵营,视为不同阵营。
备注:
对于复读的概念:

若聊天记录为

1 a

2 a

3 a

属于2,3号复读了1号的消息。

若聊天记录为

1 a

2 b

3 a

不构成任何复读,1的‘a‘和3的‘a’均属于自己原创消息。

思路:很明显的并查集。。但是。。脑子短路了一下,想歪了,导致没有签到成功qaq,难受

#include<bits/stdc++.h>
using namespace std;
#define N 100005
int fa[N];
int sum[N];
int find(int x)
{
	if(x==fa[x])
		return x;
	return fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
	int fx=find(x),fy=find(y);
	if(fx==fy)
		return;
	fa[fx]=fy;
}
int main()
{
	int n,m,x,pre;
	string s=" ",sx;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		fa[i]=i;
	}
	for(int i=0;i<m;i++)
	{
		scanf("%d",&x);
		cin>>sx;
		if(sx==s)
			merge(pre,x);
		s=sx;
		pre=x;
	}
	for(int i=1;i<=n;i++)  //刚开始的时候在merge里面就统计了子结点个数,那时候路径还没压缩完,导致会出错。。wa了五次,fo了
	{
		sum[find(i)]++;
	}
	for(int i=1;i<=n;i++)
	{
		if(i!=1)
			printf(" ");
		printf("%d",sum[fa[i]]-1);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43693379/article/details/89424763
今日推荐