Baek Jun(4195号)-友達ネットワーク


質問元:https://www.acmicpc.net/problem/4195
質問する

  • ミンヘはソーシャルサイトで友達を作るのが好きな友達です.切手収集のように、ミンヘの趣味はソーシャルサイトで友达を集めることです.

  • あるサイトの友達関係が現れる順番に並べば、2人の友達ネットワークに何人いるかを判断するプログラムを作成することができます.

  • 友人ネットワークとは,友人関係だけで移動できる関係である.
  • import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.StringTokenizer;
    
    public class Main {
    
        private static int[] parents, cnt;
    
        private static void makeSet(int n) {
            parents = new int[n];
            cnt = new int[n];
    
            for (int i = 0; i < n; i++) {
                parents[i] = i;
                cnt[i] = 1;
            }
        }
    
        private static boolean unionSet(int a, int b) {
            int parentA = findSet(a);
            int parentB = findSet(b);
    
            if (parentA == parentB) return false; // 이미 같은 집합
    
            parents[parentB] = parentA;
            cnt[parentA] += cnt[parentB];
    
            return true;
        }
    
        private static int findSet(int a) {
            if (a == parents[a]) return a;
    
            return parents[a] = findSet(parents[a]); // Path Compression
        }
    
        public static void main(String[] args) throws IOException {
            StringBuilder sb = new StringBuilder();
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    
            int T = Integer.parseInt(reader.readLine()); // 테스트케이스 개수
    
            while (T-- > 0) {
                int F = Integer.parseInt(reader.readLine()); // 친구 관계의 수
    
                Map<String, Integer> map = new HashMap<>();
                int index = 0;
    
                makeSet(F * 2);
    
                for (int i = 0; i < F; i++) {
                    StringTokenizer tokenizer = new StringTokenizer(reader.readLine());
                    String a = tokenizer.nextToken();
                    String b = tokenizer.nextToken();
    
                    if (!map.containsKey(a)) map.put(a, index++);
                    if (!map.containsKey(b)) map.put(b, index++);
    
                    unionSet(map.get(a), map.get(b));
    
                    sb.append(cnt[parents[map.get(a)]]).append("\n");
                }
            }
    
            System.out.println(sb);
        }
    
    }
    
    これは
  • Union-Findアルゴリズムに少し追加した方法で解決できる問題です.
  • 最初の問題をよく読まなかったが、ArrayIndexOutOfBoundsには例外があった.
  • に入力された「F」の値は、友人数ではなく友人関係数であり、それを友人数配列の大きさに変換したため、エラーが発生した.
  • の友人の数が特定できないため、最大の数である友人関係数*2とする.
  • 各代表者の星の下には、子供の数を記録する配列が別途設けられている.
  • Union演算を実行すると、代表者が変わり、変更する前に自分の下の数字に新しい代表の数を加えて値を更新します.