Notice
Recent Posts
Recent Comments
Link
«   2025/02   »
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
Tags
more
Archives
Today
Total
관리 메뉴

코드와이

[BAEKJOON] 17471. 게리맨더링 본문

acmicpc

[BAEKJOON] 17471. 게리맨더링

코드와이 2021. 4. 13. 23:29

 

문제링크

www.acmicpc.net/problem/17471

 

17471번: 게리맨더링

선거구를 [1, 4], [2, 3, 5, 6]으로 나누면 각 선거구의 인구는 9, 8이 된다. 인구 차이는 1이고, 이 값보다 더 작은 값으로 선거구를 나눌 수는 없다.

www.acmicpc.net

 

package acmicpc.Gold5;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class 게리맨더링 {

	static int n, total, ans;
	static int[] arr;
	static int[][] connect;
	static boolean[] visited;
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		
		n = Integer.parseInt(br.readLine());
		
		st = new StringTokenizer(br.readLine());
		
		total = 0;				// 모든 인구 수의 합
		arr = new int[n+1];
		for(int i = 1 ; i <= n ; i++) {
			arr[i] = Integer.parseInt(st.nextToken());
			total += arr[i];
		}

		connect = new int[n+1][n+1];
		for(int i = 1 ; i <= n ; i++) {
			st = new StringTokenizer(br.readLine());
			int e = Integer.parseInt(st.nextToken());
			
			for(int j = 0 ; j < e ; j++) {
				int t = Integer.parseInt(st.nextToken());
				connect[i][t] = 1;
			}
		}
		
		if(n == 2) {
			System.out.println(Math.abs(arr[1] - arr[2]));
		} else {
			ans = Integer.MAX_VALUE;
			visited = new boolean[n+1];
			set(1);
			
			System.out.println(ans == Integer.MAX_VALUE ? -1 : ans);
		}
	}
	
	// 두 쌍을 다 구하기
	private static void set(int idx) {
		if(idx == n+1) {
			if(checking()) {
				int s = solve();
				ans = Math.min(ans, s);
			}
			
			return;
		}
		
		visited[idx] = true;
		set(idx+1);
		visited[idx] = false;
		set(idx+1);
	}
	
	// 가능한 나눔인지 확인
	private static boolean checking() {
		
		// 하나의 그룹이면 false
		int cnt = 0;
		int s1 = 0;
		int s2 = 0;
		for(int i = 1 ; i <= n ; i++) {
			if(visited[i]) {
				cnt++;
				s1 = i;
			} else {
				s2 = i;
			}
		}
		if(cnt == n || cnt == 0) return false;
		
		// 두 개의 그룹이 각자 안 이어져있으면 false
		boolean[] check = new boolean[n+1];
		int num = 2;
		Queue<Integer> queue = new LinkedList<>();
		queue.add(s1);
		check[s1] = true;
		
		while(!queue.isEmpty()) {
			int x = queue.poll();
			
			for(int i = 1 ; i <= n ; i++) {
				if(visited[i] && connect[x][i] == 1 && !check[i]) {
					num++;
					check[i] = true;
					queue.add(i);
				}
			}
		}
		
		check = new boolean[n+1];
		queue = new LinkedList<>();
		queue.add(s2);
		check[s2] = true;
		
		while(!queue.isEmpty()) {
			int x = queue.poll();
			
			for(int i = 1 ; i <= n ; i++) {
				if(!visited[i] && connect[x][i] == 1 && !check[i]) {
					num++;
					check[i] = true;
					queue.add(i);
				}
			}
		}
		
		if(num != n) return false;
		
		return true;
	}

	// 가능하면 두 그룹 간의 차 구하기
	private static int solve() {
		
		int sum = 0;
		for(int i = 0 ; i <= n ; i++) {
			if(visited[i]) sum += arr[i];
		}
		return Math.abs((total - sum) - sum);
	}
}

'acmicpc' 카테고리의 다른 글

[BAEKJOON] 11052. 카드 구매하기  (0) 2021.04.15
[BAEKJOON] 1194. 달이 차오른다, 가자.  (0) 2021.04.14
[BAEKJOON] 14501. 퇴사  (0) 2021.04.13
[BAEKJOON] 1010. 다리놓기  (0) 2021.04.13
[BAEKJOON] 1238. 파티  (0) 2021.04.12