티스토리 뷰

알고리즘/BOJ

[백준] 17471 게리맨더링

세진짱 2020. 2. 8. 16:10

 

완탐으로 풀 수 있어서 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.Scanner;
 
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>2System.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];
                }
                if(can()) ans = Math.min(ans, Math.abs(A-B));
            }
            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
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/04   »
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
글 보관함