一个社交平台上有 NN 名用户,其中,有 MM 对用户是互相关注的,有 KK 对用户是互相拉黑的。
当用户 ii 和用户 jj 满足以下条件时,用户 jj 就是用户 ii 的“推荐用户”:
- 用户 ii 可以与 用户 jj 通过若干对用户的互相关注关系连接起来。(比如用户 1 与用户 2,用户 2 与用户 3 都互相关注,则用户 1 和 用户 3 就可以通过他们的关系连接起来)
- 用户 ii 与用户 jj 没有互相关注或互相拉黑。
求每位用户的“推荐用户”的数量。
数据保证不会存在一对用户既互相关注又互相拉黑。
Constraints
- 输入的所有数值都是整数。
- 2 ≤ N ≤ 10^52≤N≤105
- 0 \leq M \leq 10^50≤M≤105
- 0 \leq K \leq 10^50≤K≤105
- 1 \leq A_i, B_i \leq N1≤Ai,Bi≤N
- A_i \neq B_iAi=Bi
- 1 \leq C_i, D_i \leq N1≤Ci,Di≤N
- C_i \neq D_iCi=Di
- (A_i, B_i) \neq (A_j, B_j) (i \neq j)(Ai,Bi)=(Aj,Bj)(i=j)
- (A_i, B_i) \neq (B_j, A_j)(Ai,Bi)=(Bj,Aj)
- (C_i, D_i) \neq (C_j, D_j) (i \neq j)(Ci,Di)=(Cj,Dj)(i=j)
- (C_i, D_i) \neq (D_j, C_j)(Ci,Di)=(Dj,Cj)
- (A_i, B_i) \neq (C_j, D_j)(Ai,Bi)=(Cj,Dj)
- (A_i, B_i) \neq (D_j, C_j)(Ai,Bi)=(Dj,Cj)
Input
第一行输入三个正整数 N,M,KN,M,K;
接下来 MM 行,每行两个正整数 A_i,B_iAi,Bi,表示一对互相关注的用户
再接下来 KK 行,每行两个正整数 C_i,D_iCi,Di,表示一对互相拉黑的用户。
Output
输出用空格隔开的 NN 个整数,第 ii 个数表示用户 ii 的“推荐用户”的数量。
样例输入
4 4 1
2 1
1 3
3 2
3 4
4 1
样例输出
0 1 0 1
输入
10 9 3
10 1
6 7
8 2
2 5
8 4
7 3
10 9
6 4
5 8
2 6
7 5
3 1
输出
1 3 5 4 3 3 3 3 1 0
这道题呢,其实就是一个简单的并查集问题,只是多了一个计数。
假设1这个集体中有5个人,统计与1直接相关的2人,那么还剩下三人,接下来就是看这三个人中有几个拉黑的,最后相减输出即可。
ok,下面就是ac的代码(有兴趣的可以试一下带权)
#include<iostream>
using namespace std;
const int N=1e5+10;
int q[N]; // 根节点
int w[N]; // 关注用户
int p[N]; // 拉黑用户
int fl[N]; // 各个节点人数
int find(int x){
if(q[x]!=x){
q[x]=find(q[x]);
}
return q[x];
}
int main(){
int n,m,k;
int a,b;
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
q[i]=i;
w[i]++;
}
for(int i=1;i<=m;i++){
scanf("%d%d",&a,&b);
w[a]++;
w[b]++;
q[find(a)]=find(b);
}
for(int i=1;i<=k;i++){
cin>>a>>b;
if(find(a)==find(b)){
p[a]++;
p[b]++;
}
}
for(int i=1;i<=n;i++){
fl[find(i)]++;
}
for(int i=1;i<=n;i++){
if(fl[find(i)]-w[i]-p[i]>0){
cout<<fl[find(i)]-w[i]-p[i]<<" ";
}else cout<<"0 ";
}
}