SDNU1129.多度人脉

Description

艾斯蒂恩优公司最近打算推出一款社交网站,为了让更多用户之间互加好友,项目经理ZZK准备推出多度人脉功能。我们知道,人脉是我们直接的好友,那么多度人脉就是包括好友的好友以及好友的好友的好友等等,也就是除了直接好友之外能间接认识的所有好友。现在,ZZK给你网站数据库里所有的用户关系信息,希望你能将所有用户的多度人脉统计出来,并制作一个排行榜,看谁的多度人脉最多!

Input

第1行为该网站所有账户的个数n以及所有账户之间好友关系的个数m(1<=n<=4000,1<=m<=40000)
第2行到第m+1行为账户之间的好友关系,每行包括两个账户名,表示这两个账户互为好友,给定的数据不会有重复的关系(A B与B A是一个关系)。其中账户名最长为20个字符,全部为英文字母,账户名区分大小写。

Output

输出n行,每行包括一个多度人脉数量,多度人脉从大到小进行排序。

Sample Input

6 5
SYC ZZK
ZZK WC
SYC WC
SYC LG
WZ LZC

Sample Output

2
1
1
0
0
0

Hint

SYC的多度人脉为0
ZZK的多度人脉为1(LG)
WC的多度人脉为1(LG)
LG的多度人脉为2(ZZK、WC)
WZ的多度人脉为0
LZC的多度人脉为0

思路 

关系不会重复,所以通过并查集合并彼此存在关系的人都会被存在一个树里,只要用树的总结点树减去个人所直接连接的人(包括自己)就得到了间接好友的数量。

思路是这样,但这个题有一个很大的坑点就是他的测试点存在自己可以是自己的好友的情况,一度让我WA到怀疑人生 ,下面是ac代码

#include<bits/stdc++.h>
using namespace std;
map<int,int>c;
map<string,int>d;
map<int,int>e;
int tr[4005];
int find(int a){
	return tr[a]==a?tr[a]:tr[a]=find(tr[a]);
}
void hebing(int a,int b){
	int f1=find(a);
	int f2=find(b);
	if(f1==f2){
		return;
	}
	else{
		e[f2]+=e[f1];
		tr[f1]=f2;
	}
}
string f[4005];
string s1[40005];
string s2[40005];
int main(){
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=4005;i++){
		tr[i]=i;
	}
	int k=1;
	for(int i=1;i<=m;i++){
		cin>>s1[i]>>s2[i];
		if(!d.count(s1[i])){
			d.insert({s1[i],k});
			f[k]=s1[i];
			k++;
		}
		if(!d.count(s2[i])){
			d.insert({s2[i],k});
			f[k]=s2[i];
			k++;
		}
	}
	for(int i=1;i<=m;i++){
		c[d[s1[i]]]++;
		c[d[s2[i]]]++;
		e[d[s1[i]]]=1;
		e[d[s2[i]]]=1;
	}
	for(int i=1;i<=m;i++){
		hebing(d[s1[i]],d[s2[i]]);
	}
	int sum[4005];
	for(int i=1;i<k;i++){
//		cout<<e[find(d[f[i]])]<<endl;
		sum[i]=max(e[find(d[f[i]])]-c[d[f[i]]]-1,0);
	}
	sort(sum+1,sum+k,greater<int>());
	for(int i=1;i<k;i++){
		cout<<sum[i]<<endl;
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值