문제풀이/백준oj

[백준OJ] 4195번 친구 네트워크

Hyeon-Uk 2021. 8. 29. 23:04
반응형

https://www.acmicpc.net/problem/4195

 

4195번: 친구 네트워크

첫째 줄에 테스트 케이스의 개수가 주어진다. 각 테스트 케이스의 첫째 줄에는 친구 관계의 수 F가 주어지며, 이 값은 100,000을 넘지 않는다. 다음 F개의 줄에는 친구 관계가 생긴 순서대로 주어진

www.acmicpc.net


 

 

풀이

입력받은 이름들을 숫자로 매핑해준뒤, Find-Union 알고리즘을 이용해서 네트워크를 연동시켜준다. 이때, 연결하고 카운팅을 하면 시간초과가 날 수 있으므로, 네트워크를 연결함과 동시에, 부모노드에 다른하나에 연결된 노드의 cnt를 더해준뒤, 부모노드의 cnt를 리턴해주면 시간초과가 나지 않고 값을 바로 구할 수 있게된다.

또한, 친구관계를 최대 100,000개 입력받는다 했으므로, parent배열은 최악의 수를 고려해서 2배인 200,001개를 할당해주어야 한다.

 

코드

#include<iostream>
#include<algorithm>
#include<map>
#include<string>
using namespace std;
typedef struct node {
	int pa;
	int cnt;
}node;
int t, n;
node parent[200010];

int find(int a) {
	if (a == parent[a].pa) {
		return a;
	}
	else return find(parent[a].pa);
}


int union_parent(int a, int b) {
	a = find(a);
	b = find(b);
	//서로 다른 두 집합일때
	if (a > b) {
		parent[a].pa = b;//집합 union
		parent[b].cnt += parent[a].cnt;//부모노드에 cnt 추가
		return parent[b].cnt;
	}
	else if(a<b){
		parent[b].pa = a;//집합 union
		parent[a].cnt += parent[b].cnt;//부모노드에 cnt추가
		return parent[a].cnt;
	}
	//같은집합이면 바로 리턴
	else {
		return parent[a].cnt;
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> t;
	while (t--) {
		map<string, int> p;
		int total = 0;
		cin >> n;
		for (int i = 0; i < 200010; i++) {
			parent[i] = { i,1 };
		}
		
		for (int i = 0; i < n; i++) {
			string n1, n2;
			cin >> n1 >> n2;
			if (!p[n1]) {
				p[n1] = ++total;
			}
			if (!p[n2]) {
				p[n2] = ++total;
			}
			int i1 = p[n1];
			int i2 = p[n2];
			cout << union_parent(i1, i2) << "\n";
		}
	}
	return 0;
}

 

반응형