AtCoder Beginner Contest 157 D.Friend Suggestions

AtCoder Beginner Contest 157 D.Friend Suggestions

题目链接

Problem Statement

(略)

Constraints

(略)

Input

Sample Input 1

4 4 1
2 1
1 3
3 2
3 4
4 1

Sample Output 1

0 1 0 1

Sample Input 2

5 10 0
1 2
1 3
1 4
1 5
3 2
2 4
2 5
4 3
5 3
4 5

Sample Output 2

0 0 0 0 0

Sample Input 3

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

Sample Output 3

1 3 5 4 3 3 3 3 1 0

题目太冗长了,用markdown慢慢编辑很麻烦,就省略了……
这题比较长,其实不难,就是简单并查集,思路如下:
条件:对某个人 i i i j j j与之无直接关系,且两者都在集合 f r i e n d s h i p friendship friendship
1.用 a n s [ i ] ans[i] ans[i] 数组记录与 i i i 同在集合 f r i e n d s h i p friendship friendship 中且有 b l o c k s h i p blockship blockship 关系的人的数量
2.用 s u m [ i ] sum[i] sum[i] 数组记录集合 f r i e n d s h i p friendship friendship 的元素个数
3.对第 i i i 个人,答案 c n t = s u m [ i ] − a n s [ i ] − 1 cnt=sum[i]-ans[i]-1 cnt=sum[i]ans[i]1 ,减1就是减去自身

AC代码如下:

#include
using namespace std;
typedef long long ll;
const int N=1e5+5;

int father[N],sum[N],ans[N];
int n,m,k,x,y;

int Findfather(int x){
    return father[x]==x?x:father[x]=Findfather(father[x]);
}

void Union(int a,int b){
    a=Findfather(a),b=Findfather(b);
    if(a!=b) father[b]=a,sum[a]+=sum[b];
}

void init(){
    for(int i=0;i<=n;i++)
        father[i]=i,sum[i]=1;
}

int main(){
    scanf("%d%d%d",&n,&m,&k);
    init();
    while(m--){
        scanf("%d%d",&x,&y);
        ans[x]++,ans[y]++;
        Union(x,y);
    }
    while(k--){
        scanf("%d%d",&x,&y);
        if(Findfather(x)==Findfather(y)) ans[x]++,ans[y]++;
    }
    for(int i=1;i<=n;i++){
        printf("%d ",sum[Findfather(i)]-ans[i]-1);
    }
    return 0;
}

你可能感兴趣的:(AtCoder,并查集)