Problem C、小花梨判连通
时间限制:2000ms 空间限制:512MB
Description
小花梨给出??个点,让??位同学对这??个点任意添加无向边,构成??张图。小花梨想知道对于
每个点??,存在多少个点??(包括??本身),使得??和??在这??张图中都是连通的。
Input
第一行输入两个正整数??和??,分别表示点的个数和同学数。
接下来分成??部分进行输入,每部分输入格式相同。
每部分第一行输入一个整数????,表示第??位同学连边的数目。
接下来????行,每行两个正整数??, ??,表示第??位同学将点??和点??之间进行连接。
可能会存在重边或者自环。
(1 ≤ ?? ≤ 100000,1 ≤ ?? ≤ 10,1 ≤ ??, ?? ≤ ??, 0 ≤ ???? ≤ 200000)
Output
输出??行,第??行输出在??张图中都和编号为??的点连通的点的数目(包括??本身)
Example
Sample Input
4 2
3
1 2
1 3
2 3
2
1 2
3 4
Sample Output
2
2
1
1
对每一个图dfs求联通块并染色,处于同一个联通块中的点染成相同的颜色。染色之后对于图中的每一个点就有一个长度为k的颜色序列,两点在k张图中均联通即两个点的颜色序列完全相同。求每个点的颜色序列的hash值,并记录每种hash值出现了多少次。输出答案时将该点对应的hash值出现的次数输出即可。
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 100;
const int inf = 0x3f3f3f3f;
bool vis[maxn];
vector<int> e[11][maxn];
unsigned long long ans[maxn];
int c[11][maxn];
int col = 0;
map<unsigned long long, int> mp;
void dfs(int deep, int now) {
if (vis[now]) return;
c[deep][now] = col;
vis[now] = true;
for (auto p:e[deep][now]) {
dfs(deep, p);
}
}
int main() {
//freopen("in.txt", "r", stdin);
int n, k, m;
scanf("%d %d", &n, &k);
int u, v;
for (int i = 0; i < k; i++) {
cin >> m;
for (int j = 0; j < m; j++) {
scanf("%d %d", &u, &v);
e[i][u].push_back(v);
e[i][v].push_back(u);
}
col = 0;
memset(vis, 0, sizeof(vis));
for (int j = 1; j <= n; j++) {
if (!vis[j]) col++;
dfs(i, j);
}
}
unsigned long long hash;
for (int i = 1; i <= n; i++) {
hash = 0;
for (int j = 0; j < k; j++) {
hash = hash * mod + c[j][i];
}
mp[hash]++;
ans[i] = hash;
}
for (int i = 1; i <= n; i++) {
cout << mp[ans[i]] << endl;
}
return 0;
}
原文地址:https://www.cnblogs.com/albert-biu/p/10886808.html
时间: 2024-10-04 22:36:16