问题 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;
}