2019上海市高校大学生程序设计邀请赛(华东理工) C 小花梨判连通 并查集+map

问题 C: 小花梨判连通

时间限制: 1 Sec  内存限制: 128 MB
提交: 71  解决: 33
[提交] [状态] [命题人:admin]

题目描述

小花梨给出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

 

[提交][状态]

思路:用并查集进行染色,然后用map确定个数

算是头一回知道vector也能放在map里映射吧

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
int fa[maxn], n;
vector<int> s[maxn];
map<vector<int>, int> p;

void init() {
    for (int i = 1; i <= n; i++)
        fa[i] = i;
}

int Find(int x) {
    return fa[x] == x ? x : fa[x] = Find(fa[x]);
}

void Union(int x, int y) {
    int fx = Find(x), fy = Find(y);
    if (fx != fy) {
        if (fx < fy) fa[fy] = fx;
        else fa[fx] = fy;
    }
}

int main() {
    int k;
    scanf("%d%d", &n, &k);
    while (k--) {
        int m, u, v;
        scanf("%d", &m);
        init();
        while (m--) {
            scanf("%d%d", &u, &v);
            Union(u, v);
        }
        for (int i = 1; i <= n; i++) {
            s[i].push_back(Find(i));
        }
    }
    for (int i = 1; i <= n; i++)
        p[s[i]]++;
    for (int i = 1; i <= n; i++) {
        printf("%d\n", p[s[i]]);
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值