4195번 - 친구 네트워크
2024-07-09
#JAVA#백준
문제 풀이 시간 : 1시간
문제 요약
- •
어떤 사이트의 친구 관계가 생긴 순서대로 주어진다.
- •
두 사람의 친구 네트워크에 몇 명이 있는지 구하라.
- •
첫째 줄에 테스트 케이스의 개수가 주어진다.
- •
각 테스트 케이스의 첫째 줄에 친구 관계의 수 F ( ≤ 100,000) 가 주어진다.
- •
다음 F 개의 줄에는 친구 관계가 생긴 순서대로 주어진다.
문제 풀이
이 문제는 그냥 골드2에 비해 쉬워보여서 선택했다.
처음에는 무지성으로 해시맵에 그냥 이름, 친구 수 를 넣어서 친구가 추가될 때마다 두 명의 친구 수를 합해서 업데이트 해주면 되는거 아닌가?
라는 생각으로 코드를 짰다.
아래와 같은 코드를 이용해서
network 라는 해시맵에 해당 이름이 있다면 해당 이름의 친구 수를 가져오고,
없다면 1을 가져와 두 사람의 친구수의 합을 구했다.
그렇게 구한 새로운 친구 수를 network에 업데이트 하고, 출력하여 아주 쉽게 풀었다고 생각했는데..
num = network.getOrDefault(n1, 1) + network.getOrDefault(n2, 1);
초기 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.Provider;
import java.util.*;
public class Main {
public static int N, F;
public static HashMap<String, Integer> network;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
N = Integer.parseInt(br.readLine());
network = new HashMap<>();
for (int i = 0; i < N; i++) {
F = Integer.parseInt(br.readLine());
network.clear();
for (int j = 0; j < F; j++) {
String n1, n2;
int num;
st = new StringTokenizer(br.readLine());
n1 = st.nextToken();
n2 = st.nextToken();
num = network.getOrDefault(n1, 1) + network.getOrDefault(n2, 1);
network.put(n1, num);
network.put(n2, num);
System.out.println(num);
}
}
}
}
하지만 38%에서 틀렸다 가 떴다.
이유를 알아봤더니
만약 입력이 아래와 같이 주어졌다면
a b
b c
a c
위의 코드에서는 2, 3, 5 를 출력하게 된다.
실제 결과는 2, 3, 3 이 나와야 한다.
위 코드에서는 실제로 친구 관계에 속해있는 것을 구분하지 못하는 것이다.
이걸 해결하기 위해 나는 다시 Union - Find 를 꺼내게 되었다.
하지만 이번에는 일반 Union - Find 와 달리 배열로 구현을 할 수가 없어서 위의 코드와 같이 해시맵을 사용했는데, 그렇게 하면 친구 수를 저장할 방법이 없어서 아래와 같이 새로운 해시맵을 또 만들었다.
public static HashMap<String, String> network; //Union-find를 위한 해시맵
public static HashMap<String, Integer> friendNum; //친구 수 검색을 위한 해시맵
결과 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
public static int N, F;
public static HashMap<String, String> network;
public static HashMap<String, Integer> friendNum;
public static String find(String name) {
if (!network.get(name).equals(name)) { //부모 이름과 자신의 이름이 같지 않으면
network.put(name, find(network.get(name))); //부모 찾아서 업데이트
}
return network.get(name); //부모 리턴하기
}
public static void union(String n1, String n2) { //새로운 친구 관계 맺기
String p1 = find(n1); //두 부모 찾기
String p2 = find(n2);
int num1 = friendNum.get(p1);
int num2 = friendNum.get(p2);
if (!p1.equals(p2)) {
network.put(p2, p1);
friendNum.put(p1, num1 + num2); //부모의 친구 수 업데이트
}
}
public static int getFriendNum(String name) {
String parent = find(name); //부모 찾기
return friendNum.get(parent); //부모를 기준으로 친구 수 가져오기
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
StringBuffer sb = new StringBuffer();
N = Integer.parseInt(br.readLine());
network = new HashMap<>();
friendNum = new HashMap<>();
for (int i = 0; i < N; i++) {
F = Integer.parseInt(br.readLine());
network.clear();
friendNum.clear();
for (int j = 0; j < F; j++) {
String n1, n2;
st = new StringTokenizer(br.readLine());
n1 = st.nextToken();
n2 = st.nextToken();
if (!network.containsKey(n1)) { //해당 이름이 처음 나왔다면 초기 세팅
network.put(n1, n1); //부모 자신으로
friendNum.put(n1, 1); //친구 수 1
}
if (!network.containsKey(n2)) { //해당 이름이 처음 나왔다면 초기 세팅
network.put(n2, n2); //부모 자신으로
friendNum.put(n2, 1); //친구 수 1
}
String p1 = find(n1);
String p2 = find(n2);
if (!p1.equals(p2)) { //두 부모가 일치하지 않으면 새로운 친구관계 맺기
union(n1, n2);
}
sb.append(getFriendNum(n1)).append("\n");
}
}
System.out.println(sb);
}
}