#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
#include <cmath>
#define INF 987654321
using namespace std;
bool graph[11][11]; //인접 행렬
int population[11]; //인구수
int N; //구역 개수
bool used[11];
bool check[11];
int ret = INF;
void isConnect() {
//used = true 인 구역 연결 확인
memmove(check, used, sizeof(check));
int target = -1;
for (int i = 1; i <= N; i++) {
if (check[i]) {
target = i;
break;
}
}
if (target == -1) return;
queue<int> q;
q.push(target);
while (!q.empty()) {
int front = q.front();
check[front] = false;
q.pop();
for (int i = 1; i <= N; i++) {
if (graph[front][i] && check[i]) {
q.push(i);
}
}
}
bool is_conn = true;
for (int i = 1; i <= N; i++) {
if (check[i]) is_conn = false;
}
//연결 안된 구역 있다면 return
if (!is_conn) return;
//used = false 인 구역 연결 확인
memmove(check, used, sizeof(check));
target = -1;
for (int i = 1; i <= N; i++) {
if (!check[i]) {
target = i;
break;
}
}
queue<int> q2;
q2.push(target);
while (!q2.empty()) {
int front = q2.front();
check[front] = true;
q2.pop();
for (int i = 1; i <= N; i++) {
if (graph[front][i] && !check[i]) {
q2.push(i);
}
}
}
is_conn = true;
for (int i = 1; i <= N; i++) {
if (!check[i]) is_conn = false;
}
//연결 안된 구역 있으면 return
if (!is_conn) return;
//두 구역이 모두 각각 연결상태라면 인구수 차이 비교
int sum1 = 0;
int sum2 = 0;
for (int i = 1; i <= N; i++) {
if (used[i]) {
sum1 += population[i];
}
else {
sum2 += population[i];
}
}
int diff = abs(sum1 - sum2);
ret = min(ret, diff);
}
void dfs(int idx, int toPick) {
if (toPick == 0) {
isConnect();
return;
}
for (int i = idx; i <= N; i++) {
if (!used[i]) {
used[i] = true;
dfs(i, toPick - 1);
used[i] = false;
}
}
}
int main() {
scanf("%d", &N);
for (int i = 1; i <= N; i++) {
scanf("%d", &population[i]);
}
for (int i = 1; i <= N; i++) {
int cnt;
scanf("%d", &cnt);
for (int j = 0; j < cnt; j++) {
int temp;
scanf("%d", &temp);
graph[i][temp] = 1;
graph[temp][i] = 1;
}
}
for (int i = 1; i <= N; i++) {
dfs(0, i);
}
if (ret == INF) {
printf("%d\n", -1);
}
else{
printf("%d\n", ret);
}
return 0;
}
1. 선거구를 나누는 방법은 최대 10C1 + 10C2 + ... + 10C9 + 10C10 이라서 2046가지이다.
2. dfs() 함수가 선거구를 선택하는 조합을 찾고, isConnect() 함수로 나눠진 구역의 연결 상태를 확인, 인구 수 차이를 비교한다.
3. isConnect() 함수에서 연결 여부를 판단할 때 bfs를 사용했다. dfs()로 한 가지 경우를 찾았을 때 used값이 true인 구역과 false인 구역으로 나누어진다. 이 때 true인 구역끼리의 연결 여부를 bfs로 체크하고, false 인 구역끼리의 연결 여부도 bfs로 체크한다. 그리고 각각의 구역이 연결되어있는 경우 인구수 차이를 계산해서 현재 ret 값보다 작다면 ret를 갱신한다.
* 연결 여부를 체크할 수 있는 다른 방법이 있는지 생각해 볼 것.