백준 [17471] 게리맨더링
문제보기
소스코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
static int N, ans;
static int[] popul;
static int[][] adj;
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
ans = 987654321;
popul = new int[N];
adj = new int[N][N];
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < N; i++) {
popul[i] = Integer.parseInt(st.nextToken());
}
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
int cnt = Integer.parseInt(st.nextToken());
for (int j = 0; j < cnt; j++) {
int area = Integer.parseInt(st.nextToken()) - 1;
adj[i][area] = 1;
adj[area][i] = 1;
}
}
pick(new boolean[N], 0, 0);
if (ans == 987654321)
ans = -1;
System.out.println(ans);
}
public static void pick(boolean[] sel, int idx, int cnt) {
if (idx == sel.length) {
if (cnt != 0 && cnt != N)
chk(sel);
return;
}
sel[idx] = false;
pick(sel, idx + 1, cnt + 1);
sel[idx] = true;
pick(sel, idx + 1, cnt);
}
public static void chk(boolean[] sel) {
int flagF = -1;
int flagT = -1;
int cntF = 0;
int cntT = 0;
boolean result = true;
for (int i = 0; i < N; i++) {
flagChk = false;
if (!sel[i]) {
if (flagF < 0) {
flagF = i;
cntF += popul[i];
continue;
} else {
// 이어져있는지 체크
isConnect(new boolean[N][N], sel, i, flagF, false);
if (!flagChk) {
result = false;
break;
}
flagF = i;
cntF += popul[i];
}
} else {
if (flagT < 0) {
flagT = i;
cntT += popul[i];
continue;
} else {
isConnect(new boolean[N][N], sel, i, flagT, true);
if (!flagChk) {
result = false;
break;
}
flagT = i;
cntT += popul[i];
}
}
}
if (result) {
int diff = Math.abs(cntF - cntT);
ans = Math.min(ans, diff);
}
}
static boolean flagChk;
public static void isConnect(boolean[][] v, boolean[] sel, int i, int flag, boolean chk) {
// 가는길에 반대 flag 만나면 연결될 수 없다.
for (int k = 0; k < N; k++) {
if (v[i][k] || adj[i][k] == 0 || sel[k] != chk)
continue;
if (adj[i][k] == 1) {
if (k == flag) {
flagChk = true;
break;
} else {
v[i][k] = true;
v[k][i] = true;
isConnect(v, sel, k, flag, chk);
}
}
}
}
}