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 | #include <cstdio> #include <vector> #include <queue> #include <functional> typedef long long int ll; using namespace std; const int N = 100001; void change(int& x, int& y) { int k; k = x; x = y; y = k; } vector <int> v[N]; priority_queue <int, vector<int>, greater<int> > pq; int n, ar[N], dist[N], ep, ep_v, ind[N], dist_i[N]; int main(void) { int a, b; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &ar[i]); for (int i = 1; i < n; i++) { scanf("%d %d", &a, &b); if (a > b) change(a, b); v[b].push_back(a); ind[a]++; } for (int i = 1; i <= n; i++) { if (ind[i] == 0) { pq.push(i); dist[i] = ar[i]; dist_i[i] = i; } } while (!pq.empty()) { int e = pq.top(); pq.pop(); for (int i = 0; i < v[e].size(); i++) { int to = v[e][i]; ind[to]--; if (dist[e] + ar[to] >= dist[to] && dist_i[to] < dist_i[e]) { dist[to] = dist[e] + ar[to]; dist_i[to] = dist_i[e]; } if (ind[to] == 0) pq.push(to); } } printf("%d %d", dist_i[1], dist[1]); return 0; } | cs |
서강대 3번 위상으로 풀었는데 칼같이 10점뜸
이거 예선부터 광탈할 삘임....
딴짓하다 늦게봐서 미안
일단 반례는 6 / 1 1 1 1 1 1 / 1 2 / 1 6 / 1 4 / 6 5 / 6 3 슬래쉬는 한줄띄운거
예제 테스트케이스 1번에서 정점 3과 6만 위치 바꾼거고, 5 3이 나와야 하는데 저 코드는 6 2 나옴
if (dist[e] + ar[to] >= dist[to] && dist_i[to] < dist_i[e]) 여기서 가정이 잘못된 것 같아
정점이 1 -> 6 -> 5 -> 4 -> 3 -> 2처럼 되어 있다면 6에서부터 최단경로 갱신이 멈춰버림
그리고 문제 설명을 잘 읽어보면 트리라는 것이 항상 보장되어 있고, 루트는 항상 1이니까 ind 배열 자체가 필요없음
따라서 priority_queue나 위상? 그런 거 쓸 필요가 없어 한 점에서 다른 한 점으로 가는 경로는 하나뿐이니까 그게 항상 최단경로임
나도 그래서 첨엔 단순 bfs 돌렸는데 답이 아니더라고 ㅠㅠ 반례 찾아준거 너무 ㄱㅅ bfs로 다시 또 짜봐야할듯 - dc App