BOJ 20531 인간관계
sorohue가 PS하는 블로그
BOJ 20531 인간관계
문제 링크입니다.
친구의 친구는 친구
친구의 무리 중 단 한 명이라도 친구가 되면 그 무리 전체와 친구가 됩니다. 그래서 마치 친구 무리를 한 명의 친구인 것처럼 생각해 주어도 좋습니다.
그렇다면 문제는 친구 관계가 새로 생길 때마다, 친구 무리의 수를 세서 그 수만큼의 친구가 있을 때 친구 관계가 형성되는 경우의 수를 구하면 됩니다. 친구 무리의 수를 세는 것은 분리 집합 등의 자료 구조를 이용해 두 무리가 합쳐질 때마다 무리의 수를 1씩 깎는 방식으로 쉽게 할 수 있습니다.
관계 형성
무리의 수가 정해졌다면 그에 해당하는 답을 찾아야 합니다. 귀찮으니까 모든 가능한 무리의 수에 대한 답을 미리 구해둡시다.
각 무리들을 다시 큰 무리로 각각 묶는 방법의 수는 곧 집합의 분할을 구하는 문제가 됩니다. 벨 수라는 이름이 있는 유서 깊은 문제니, 이 점화식을 그대로 써서 답을 구해 줍시다.
코드
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
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll mod = 1e9+7;
ll d[5050][5050];
int par[5050];
int comp;
int f(int x){
return par[x] < 0 ? x : par[x] = f(par[x]);
}
void u(int x, int y){
x = f(x); y = f(y);
if(x == y) return;
comp--;
if(par[x] > par[y]) swap(x, y);
par[x] += par[y];
par[y] = x;
}
int main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);
memset(par, -1, sizeof(par));
for(int i = 1; i <= 5000; i++){
d[i][0] = d[i][1] = 1;
for(int j = 2; j <= i; j++){
d[i][j] = (d[i-1][j]*j+d[i-1][j-1])%mod;
d[i][0] = (d[i][0]+d[i][j])%mod;
}
}
int n, m; cin >> n >> m; comp = n;
while(m--){
int x, y; cin >> x >> y;
u(x, y);
cout << d[comp][0] << '\n';
}
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.