小花梨判连通(并查集+map+vector连用)

小花梨判连通(并查集+map+vector连用)

题目描述

小花梨给出n个点,让k位同学对这n个点任意添加无向边,构成k张图。小花梨想知道对于每个点i,存在多少个点j(包括i本身),使得i和j在这k张图中都是连通的。

输入

第一行输入两个正整数n和k,分别表示点的个数和同学数。
接下来分成k部分进行输入,每部分输入格式相同。
每部分第一行输入一个整数ai,表示第i位同学连边的数目。
接下来ai行,每行两个正整数u,v,表示第i位同学将点u和点v之间进行连接。
可能会存在重边或者自环。(1≤n≤100000,1≤k≤10,1≤u,v≤n,0≤ai≤200000)

输出

输出n行,第i行输出在k张图中都和编号为i的点连通的点的数目(包括i本身)

样例输入

复制样例数据

4 2 
3 
1 2 
1 3 
2 3 
2 
1 2 
3 4 
样例输出
2
2
1
1

ps:每一张图,找到每个点的祖先,如果这个点的每张图的祖先和另外一个点每张图的祖先都相同,则这个点在每一张图里都与另外一个点联通,map<vector<int>,int>,vector代表很多元素,只有对应位置全部相同才++;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include &lt;iostream>

#include &lt;bits/stdc++.h>

using namespace std;

const int N = 1e5+5;

int fa[N],num[N];

vector&lt;int>zu[N];

map&lt;vector&lt;int>,int>p;

int Find(int x){

    if(fa[x]==x) return x;

    return fa[x]=Find(fa[x]);

}

void Merg(int x,int y){

    int a=Find(x);

    int b=Find(y);

    if(a!=b){

        if(num[a]>num[b]){

            num[a]+=num[b];

            fa[b]=a;

        }

        else {

            num[b]+=num[a];

            fa[a]=b;

        }

    }

    return ;

}

int main()

{

    int n,k;

    cin>>n>>k;

    for(int i=0;i&lt;k;i++){

        for(int j=1;j&lt;=n;j++){

            fa[j]=j;

            num[j]=1;

        }

        int m;

        int u,v;

        scanf("%d",&amp;m);

        while(m--){

            scanf("%d%d",&amp;u,&amp;v);

            Merg(u,v);

        }

        for(int j=1;j&lt;=n;j++){

            zu[j].push_back(Find(j));//把每个点的祖先推进去

            //cout&lt;&lt;Find(j)&lt;&lt;endl;

        }

    }

    for(int i=1;i&lt;=n;i++){

        p[zu[i]]++;//如果zu[i]里对应位置元素全部相同,++;

        //printf("%d\n",p[zu[i]]);

    }

    for(int i=1;i&lt;=n;i++){

        printf("%d\n",p[zu[i]]);

    }

    return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值