처음엔 Edges 배열을 Backtracking을 이용해 순열을 구현했다.
순열을 통해 방문 순서를 바꿔가며 가중치를 가감하며 모든 경우에서 걸러내는 방식이었다.
A 배열이 모두 0이 되는 경우 중, 가감 횟수가 가장 작은 경우를 뽑아 내려고 했다.
하지만 언제나 그랬듯.. 완전 탐색은 시간 초과를 초래했다..
1차 시도 : Backtracking
#include <iostream>
#include <vector>
using namespace std;
#define BIGINT 9999999
long long res_cnt = 0, min_v = BIGINT;
bool validate(vector<int> a) {
int sum = 0;
for (int i : a)
sum += i;
if (sum == 0) return true;
else return false;
}
bool validate_zero(vector<int> a) {
for (int i : a)
if (i != 0) return false;
return true;
}
void make_all_zero(int depth, vector<int>& a, vector<vector<int>> edges, vector<bool>& visit) {
if (depth == edges.size()) {
if (validate_zero(a))
if (min_v > res_cnt)
min_v = res_cnt;
return;
}
for (int i = 0; i < edges.size(); i++) {
if (!visit[i]) {
visit[i] = true;
int front_node = a[edges[i][0]];
int back_node = a[edges[i][1]];
a[edges[i][1]] += front_node;
a[edges[i][0]] -= front_node;
res_cnt += abs(front_node);
make_all_zero(depth + 1, a, edges, visit);
visit[i] = false;
a[edges[i][1]] -= front_node;
a[edges[i][0]] += front_node;
res_cnt -= abs(front_node);
}
}
}
long long solution(vector<int> a, vector<vector<int>> edges) {
long long answer = -1;
vector<bool> visit(edges.size(), false);
if (validate(a)) {
make_all_zero(0, a, edges, visit);
answer = min_v;
}
return answer;
}
2차 시도 : Tree의 구현
시간 초과를 없애기 위해 직접 Tree를 구현한 뒤 순회해보기로 했다.
순회는 하였으나, 합을 쌓아나가는 과정에서 계속 시간초과가 발생해서
결국 검색을 통해 다른 사람의 풀이를 참고했다.
#include <iostream>
#include <vector>
using namespace std;
long long res_count = 0;
bool validate(vector<int> a) {
// 모든 Node 가중치의 합이 0이 아니면
// 애초에 DFS를 진행할 이유가 없음!
long long sum = 0;
for (int i : a)
sum += i;
if (sum == 0) return true;
else return false;
}
void init_weight(vector<long long>& weight, vector<int> a) {
for (int i = 0; i < a.size(); i++)
weight[i] = a[i];
// a의 한계치가 1,000,000이다.
// 즉, 합이 매우 커질 수 있으므로 long long으로 변환한다.
}
void make_tree(vector<vector<int>>& adj_list, vector<vector<int>> edges, vector<int> a) {
for (auto edge : edges) {
adj_list[edge[0]].push_back(edge[1]);
adj_list[edge[1]].push_back(edge[0]);
}
// Tree를 인접 리스트로 구현한다.
}
void make_all_zero(vector<vector<int>>& adj_list, vector<long long>& weight, int curr, int parent) {
// 여기서 부턴 DFS Code
for (int i = 0; i < adj_list[curr].size(); i++)
if (adj_list[curr][i] != parent)
make_all_zero(adj_list, weight, adj_list[curr][i], curr);
// 더 이상 탐방할 Node가 없다면 아래의 행동을 한다.
weight[parent] += weight[curr];
// Leaf node로 부터 Parent node에 점점 값을 쌓아간다.
// 마지막에 Root node에 쌓인 값만 0이면 됨!
res_count += abs(weight[curr]);
// 부모 노드에 쌓으면서 Count도 동시에 증가.
}
long long solution(vector<int> a, vector<vector<int>> edges) {
long long answer = -1;
vector<vector<int>> adj_list(a.size());
vector<long long> weight(a.size());
if (validate(a)) {
init_weight(weight, a);
make_tree(adj_list, edges, a);
make_all_zero(adj_list, weight, 0, 0);
answer = res_count;
}
return answer;
}