LAN 질문입니다. freestar [[problem:LAN]] 문제를 푸는 중입니다. 테스트 케이스 다 맞고, 제가 추가로 만든 예제에서도 결과가 잘 나오는데 제출하니 오답이라고 뜨네요. 조언 부탁드립니다. 방법은 모든 node 사이 edge들의 weight를 구한뒤 이미 있는 edge의 weight를 0으로 만들고 최소 스패닝 트리 알고리즘을 썼습니다. #include <stdio.h> #include <math.h> typedef struct Edge{ int n1; int n2; double dist; } EDGE; EDGE edge[124750]; int X[500], Y[500]; int C, N, M; EDGE tmp[124750]; int c = 0; int cycle[500] = { 0, }; double sum = 0.0; int num_edges = 0; void merge(int left, int mid, int right) { int l = left; int r = mid+1; int idx=0; while (l<=mid && r <=right) { if (edge[l].dist < edge[r].dist) tmp[idx++] = edge[l++]; else tmp[idx++] = edge[r++]; } while (l <= mid) tmp[idx++] = edge[l++]; while (r <= right) tmp[idx++] = edge[r++]; for (int i = left; i <= right; i++) edge[i] = tmp[i-left]; } void merge_sort(int left, int right) { if (left < right) { int mid = (left + right) / 2; merge_sort(left, mid); merge_sort(mid + 1, right); merge(left, mid, right); } } void connect(int n1, int n2, double dist) { //NO Cycle if (cycle[n1] == 0 && cycle[n2] == 0) { c++; cycle[n1] = c; cycle[n2] = c; sum += dist; num_edges++; } else if (cycle[n1] != 0 && cycle[n2] == 0) { cycle[n2] = cycle[n1]; sum += dist; num_edges++; } else if (cycle[n1] == 0 && cycle[n2] != 0) { cycle[n1] = cycle[n2]; sum += dist; num_edges++; } else if (cycle[n1] != 0 && cycle[n2] != 0 && cycle[n1] != cycle[n2]) { for (int j = 0; j < N; j++) { if (cycle[j] == cycle[n2]) cycle[j] = cycle[n1]; } sum += dist; num_edges++; } //else -> Cycle! } int main() { int i; int a, b; int total_edges; scanf("%d", &C); while (C--) { scanf("%d %d", &N, &M); for ( i = 0; i < N; i++) scanf("%d", &X[i]); for ( i = 0; i < N; i++) scanf("%d", &Y[i]); // 모든 node 간의 edge dist 구하기 total_edges = 0; for (i = 0; i < N; i++) { for (int j = i + 1; j < N; j++) { edge[total_edges].n1 = i; edge[total_edges].n2 = j; edge[total_edges].dist = sqrt(pow((double)(X[i] - X[j]), 2) + pow((double)(Y[i] - Y[j]), 2)); total_edges++; } } //이미 edge가 존재하면, 그 edge는 dist를 0으로 -> MST 만들때 가장 처음에 추가하기 위해 for ( i = 0; i < M; i++) { scanf("%d %d", &a, &b); for (int j = 0; j < total_edges; j++) { if ((edge[j].n1 == a && edge[j].n2 == b) || (edge[j].n1 ==b && edge[j].n2 == a)) { edge[j].dist = 0; //연결 connect(edge[j].n1, edge[j].n2, edge[j].dist); break; } } } merge_sort(0, total_edges - 1); for (i = 0; i < total_edges; i++) { //연결 connect(edge[i].n1, edge[i].n2,edge[i].dist); if (num_edges == N - 1) break; } printf("%.10lf\n", sum); c = 0; for (i = 0; i < N; i++) cycle[i] = 0; sum = 0.0; num_edges = 0; } return 0; } 11년 전
3개의 댓글이 있습니다. freestar 오류를 발견하고 수정 뒤 제출했습니다만, 여전히 오답 중인 상태입니다. 소스코드는 6/19일 오전 11시 20분쯤 업데이트 했습니다. 11년 전 link restart for (int j = 0; j < N; j++) { if (cycle[j] == cycle[n2]) cycle[j] = cycle[n1]; } 이부분에서 cycle[n2]가 먼저 업데이트 될 경우 문제가 발생합니다ㅠㅠ cycle[n2]를 임시변수에 저장해두고 업데이트하니 정답이 뜨는군요. 이런 data structure를 union find 혹은 disjoint-set이라고 하고, 여기에 잘 짜여진 알고리즘이 있습니다. 11년 전 link freestar 와 정말 감사합니다. ㅠㅠ 긴 소스코드를 이렇게 봐주시고 답변 해주시다니.. 감사합니다. 11년 전 link 정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.
freestar
[[problem:LAN]] 문제를 푸는 중입니다.
테스트 케이스 다 맞고, 제가 추가로 만든 예제에서도 결과가 잘 나오는데
제출하니 오답이라고 뜨네요.
조언 부탁드립니다.
방법은
모든 node 사이 edge들의 weight를 구한뒤
이미 있는 edge의 weight를 0으로 만들고
최소 스패닝 트리 알고리즘을 썼습니다.
11년 전