백준알고리즘

다리만들기2

먼지의삶 2019. 9. 27. 20:40

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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
 
struct PAIR {
    int x, y;
    PAIR(int x, int y) {
        this->= x;
        this->= y;
    }
};
 
int h, w;
int map[11][11];
int real[11][11];
bool ck = false;
bool dos[11];
bool d[11][11];
int realmap[7][7];
bool findd = false;
int ans = 987654321;
int cnt = 1;
int dx[] = { 0,0,1,-1 };
int dy[] = { 1,-1,0,0 };
class Edge {
public:
    int node[2];
    int distance;
    Edge(int a, int b, int distance) {
        this->distance = distance;
        this->node[0= a;
        this->node[1= b;
    }
    bool operator < (Edge& edge) {
        return this->distance < edge.distance;
    }
};
vector<Edge> v;
void bfs(int x, int y, int ct) {
    queue<PAIR> q;
    q.push(PAIR(x, y));
    d[x][y] = true;
    real[x][y] = ct;
    while (!q.empty()) {
        x = q.front().x;  y = q.front().y;
        q.pop();
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i]; int ny = y + dy[i];
            if (nx >= 1 && nx <= h && ny >= 1 && ny <= w) {
                if (d[nx][ny] == false && map[nx][ny] == 1) {
                    d[nx][ny] = true;
                    real[nx][ny] = ct;
                    q.push(PAIR(nx, ny));
                }
            }
        }
    }
}
bool check(int nx, int ny) {
    if (nx >= 1 && nx <= h && ny >= 1 && ny <= w) {
        return true;
    }
    return false;
}
void make_value(int x, int y, int ct, int idx) {
    int nx = x; int ny = y;
    int c = 0;
    while (true) {
        nx += dx[idx]; ny += dy[idx]; c++;
        if (check(nx, ny)) {
            if (real[nx][ny] == ct) {
                break;
            }
            else {
                if (real[nx][ny] != ct && real[nx][ny] != 0) {
                    if (c - 1 >= 2) {
                        if (realmap[ct][real[nx][ny]] == 0) {
                            realmap[ct][real[nx][ny]] = c - 1;
                            realmap[real[nx][ny]][ct] = c - 1;;
                            break;
                        }
                        if (realmap[ct][real[nx][ny]] > c - 1) {
                            realmap[ct][real[nx][ny]] = c - 1;
                            realmap[real[nx][ny]][ct] = c - 1;;
                            break;
                        }
                        else break;
                    }
                    else {
                        break;
                    }
                }
            }
        }
        else break;
    }
}
 
bool chek() {
    for (int i = 1; i < cnt; i++) {
        if (dos[i] == false) {
            return false;
        }
    }
    return true;
}
void bfs2(int idx) {
    ck = false;
    findd = false;
    queue<int> q;
    q.push(idx);
    dos[idx] = true;
    int ct = 0;;
    while (!q.empty()) {
        idx = q.front();
        //cout << idx << endl;
        q.pop();
        for (int i = 1; i < cnt; i++) {
            if (dos[i] == false && realmap[idx][i] != 0) {
                dos[i] = true;
                q.push(i);
            }
        }
    }
    for (int i = 1; i < cnt; i++) {
        if (dos[i] == false) {
            ck = true;
        }
    }
    if (ck == false && ans > ct) {
        ans = ct;
        findd = true;
    }
}
int getParent(int parent[], int a) {
    if (parent[a] == a) return a;//종료구문
    return parent[a] = getParent(parent, parent[a]);
}
//부모노드 합치기
void unionParent(int parent[], int a, int b) {
    a = getParent(parent, a);
    b = getParent(parent, b);
    if (a < b) parent[b] = a;
    else parent[a] = b;
}
//같은 부모를 가지는지 확인하기
int findParent(int parent[], int a, int b) {
    a = getParent(parent, a);
    b = getParent(parent, b);
    if (a == b) return 1;
    else return 0;
}
int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin >> h >> w;
    for (int i = 1; i <= h; i++) {
        for (int j = 1; j <= w; j++) {
            cin >> map[i][j];
        }
    }
        for (int i = 1; i <= h; i++)
    {
        for (int j = 1; j <= w; j++) {
            if (d[i][j] == false && map[i][j] == 1) {
                bfs(i, j, cnt);
                cnt++;
            }
        }
    }
 
    for (int i = 1; i <= h; i++) {
        for (int j = 1; j <= w; j++) {
            if (real[i][j] != 0) {
                for (int k = 0; k < 4; k++) {
                    make_value(i, j, real[i][j], k);
                }
            }
        }
    }
    for (int i = 1; i < cnt; i++) {
        bfs2(i);
        memset(dos, falsesizeof(dos));
    }
    if (ans == 987654321) {
        cout << -1 << '\n';
        return 0;
    }
    for (int i = 1; i < cnt; i++) {
        for (int j = i + 1; j < cnt; j++) {
            if (realmap[i][j] != 0) {
                v.push_back(Edge(i, j, realmap[i][j]));
            }
        }
    }
    //cout<<v.size()<<'\n';
        sort(v.begin(), v.end());
    /*for (int i = 0; i < v.size(); i++) {
        cout << v[i].node[0] << ' ' << v[i].node[1] << ' ' << v[i].distance << '\n';
    }*/
    bool check[11]; memset(check, falsesizeof(check));
    for (int i = 0; i < v.size(); i++) {
        check[v[i].node[0]] = true;
        check[v[i].node[1]] = true;
    }
        int parent[11];
    for (int i = 0; i < cnt; i++) {
        parent[i] = i;
    }
    int sum = 0;
 
    for (int i = 0; i < v.size(); i++) {
        if (!findParent(parent, v[i].node[0- 1, v[i].node[1- 1)) {
            sum += v[i].distance;
                unionParent(parent, v[i].node[0- 1, v[i].node[1- 1);
        }
    }
    cout << sum << '\n';
        return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

MST 알고리즘을 이용한 문제였다.

단순하게 BFS나 DFS로는 풀어내기힘든문제,

최소한의 비용으로 모든걸연결하는게 목표이므로, 그냥 연결만하는게 아니라 비용에 따른 가치도 따져야한다

그래서 반드시 MST가필요하다고 생각했고, 맵 탐색을 통해 섬 영역을 나누고 그나눠진영역을 토대로 가장짧은 다리길이를 구해서 vector에 저장하고 그것을 정렬한 뒤  MST알고리즘을 적용하면끝난다.