티스토리 뷰
완탐으로 풀 수 있어서 dfs를 이용해 풀었다
팀을 나눈 후 그래프로 표현하고 dfs를 이용해
내가 우리팀에 갈 수 있는지 체크를 하면 된다
여기서 만약 애초에 그래프가 2개 이상의 연결요소로 구성되어있다면
애초에 2개의 팀으로 나눌 수 없어서 -1 을 출력하고 종료하자!
그럼 그래프를 그린 후를 생각해보자
dfs를 이용해서 origin -> next 로 갈 수 있는지 계속 확인해보며 된다
그 후 만약 같은 팀인데 연결 되어있지않다면 false 아니면 true를 리턴해주고
만약 모든 조건을 만족한다면 팀의 합의 최소를 구해보자
소스코드 (C++)
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
int n,ans=1e9;
int cnt[11];
bool connect[11][11];
bool check[11],Team[11];
vector<vector<int>> Graph;
void dfs(int origin,int x){
check[x]=true;
for(int i=0;i<Graph[x].size();i++){
int next = Graph[x][i];
if(!check[next] && (Team[origin]==Team[next])){
connect[origin][next]=connect[next][origin]=true;
dfs(origin,next);
}
}
}
bool can(){
memset(connect,0,sizeof(connect));
for(int i=0;i<n;i++){
memset(check,0,sizeof(check));
dfs(i,i);
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i==j) continue;
if((Team[i]==Team[j]) && !connect[i][j]) return false;
}
}
return true;
}
int main(){
scanf(" %d",&n);
for(int i=0;i<n;i++) scanf(" %d",&cnt[i]);
for(int i=0;i<n;i++){
int m; scanf(" %d",&m);
for(int j=0;j<m;j++){
int k; scanf(" %d",&k); k--;
Graph[i].push_back(k);
Graph[k].push_back(i);
}
}
int c=0;
for(int i=0;i<n;i++) if(!check[i]) dfs(i,i),c++;
if(c>2){
puts("-1"); return 0;
}
for(int i=1;i<(1<<n)-1;i++){
memset(Team,0,sizeof(Team));
int Asum=0,Bsum=0;
for(int j=0;j<n;j++){
if(i&(1<<j)) Team[j]=true,Asum+=cnt[j];
else Bsum+=cnt[j];
}
if(can()) ans = min(ans,abs(Asum-Bsum));
}
printf("%d\n",ans);
}
|
소스코드 (Java)
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
import java.util.ArrayList;
public class Main {
public static int n;
public static ArrayList<Integer>[] Graph;
public static boolean[] team;
public static boolean[][] connect;
public static boolean[] check;
public static boolean[] visited;
public static int[] score;
public static void dfs(int x) {
check[x]=true;
for(int i=0;i<Graph[x].size();i++) {
int next = Graph[x].get(i);
if(!check[next]) dfs(next);
}
}
public static void solve(int original,int now) {
connect[original][now]=connect[now][original]=true;
visited[now]=true;
for(int i=0;i<Graph[now].size();i++) {
int next = Graph[now].get(i);
if(!visited[next] && (team[now]==team[next])) solve(original,next);
}
}
public static boolean can() {
connect = new boolean[n+1][n+1];
for(int i=0;i<n;i++) {
visited = new boolean[n+1];
solve(i,i);
}
for(int i=0;i<n;i++) {
for(int j=i+1;j<n;j++) {
if(team[i]==team[j] && !connect[i][j]) return false;
}
}
return true;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
score = new int[n+1];
Graph = new ArrayList[n+1];
check = new boolean[n+1];
for(int i=0;i<n;i++) Graph[i] = new ArrayList<>();
for(int i=0;i<n;i++) score[i]=sc.nextInt();
for(int i=0;i<n;i++) {
int k = sc.nextInt();
for(int j=0;j<k;j++) {
int x = sc.nextInt();
Graph[i].add(x-1);
Graph[x-1].add(i);
}
}
int cnt=0;
for(int i=0;i<n;i++) {
if(!check[i]) {
dfs(i); cnt+=1;
}
}
if(cnt>2) System.out.println(-1);
else {
int ans = 987654321;
for(int i=1;i<(1<<n)-1;i++) {
team = new boolean[n+1];
int A=0,B=0;
for(int j=0;j<n;j++) {
if((i&(1<<j))>0) {
team[j]=true; A+=score[j];
}
else B+=score[j];
}
}
System.out.println(ans);
}
}
}
|
'알고리즘 > BOJ' 카테고리의 다른 글
[백준] 3109 빵집 (0) | 2020.02.14 |
---|---|
[백준] 17281 ⚾ (0) | 2020.02.09 |
[백준] 16637 괄호 추가하기 (0) | 2020.02.08 |
[백준] 12924 멋진 숫자 쌍 (0) | 2020.02.07 |
[백준] 12919 A와 B 2 (0) | 2020.02.07 |
댓글