MOVE 문제 오답..도움을 찾습니다;;

  • coldradio
    coldradio

    MOVE문제입니다. 오답의 원인을 못찾은지도 벌써...
    ROUTING 문제와 비슷해 보여 풀만하다고 도전했는데 꽉 막혔네요;;

    알고리즘은 딕스트라+priority_queue를 썼습니다. 혹시 아래 말고 문제풀이 시 주의해야할 점이 있을까요?
    1. 두 도시 간에 복수의 도로 존재 가능. -> 입력 시, 더 짧은 길이로 덮어씀
    2. 도로는 양 방향 -> 도로 경로 입력 시, 대칭되게 neighbor vector에 넣어줌.
    2. 도로 경로 길이 0 -> 딕스트라가 경로길이>=0인 경우를 커버하는 거 같아 특별히 신경을 안 썼습니다.
    3. 도로 길이 최대값 -> 문제에 특별히 명시되지 않았는데, 혹시 모를 overflow를 대비해 딕스트라에서 중간 cost(cost_so_far)는 int64_t에 저장했습니다.
    4. 뭐가 또 있을까요?;;; 뭔가 빼먹은게 분명한데 말이죠;;

    #include <stdio.h>
    #include <map>
    #include <vector>
    #include <queue>
    #include <stdint.h>
    using namespace std;
    
    int C, N, M;
    //A,B 도시 사이 코스트 C, A<<16+B --> C
    map<int, int64_t> Link;
    #define KEY(x,y) ((x<<16)+y)
    int64_t cost_so_far[10000];
    typedef vector<int> V;
    
    struct Node {
        Node(int n) :
                n(n) {
        }
        int n;
        bool operator<(const Node &t) const {
            return cost_so_far[n] > cost_so_far[t.n];
        }
    };
    
    int64_t f(V neighbors[]) {
        priority_queue<Node> q;
        cost_so_far[0] = 0, q.push(Node(0));
        for (int i = 1; i < N; ++i)
            cost_so_far[i] = 10e17, q.push(i);  // 두도시 사이의 default cost==10e17
    
        while (q.size()) {
            Node u = q.top();
            q.pop();
            if (u.n == N - 1)
                break;
            for (V::iterator it = neighbors[u.n].begin();
                    it != neighbors[u.n].end(); ++it) {
                int64_t t = cost_so_far[u.n] + Link[KEY(u.n, *it)];
                if (t < cost_so_far[*it])
                    cost_so_far[*it] = t;
            }
        }
        return cost_so_far[N - 1];
    }
    
    int main() {
        scanf("%d", &C);
        while (--C >= 0) {
            // 이웃 도시 정보 저장 0도시 의 이웃 도시가 1,2,3이라면, neighbors[0] --> Vector[1,2,3]
            V neighbors[10000];
            scanf("%d%d", &N, &M);
            for (int i = 0; i < M; ++i) {
                int a, b, c;
                scanf("%d%d%d", &a, &b, &c);
                if (Link.find(KEY(a, b)) == Link.end() //아직 읽지 않은 경로거나
                        || (Link.find(KEY(a, b)) != Link.end() && Link[KEY(a, b)] > c)) { // 읽었지만, 짧다면
                    Link[KEY(a, b)] = Link[KEY(b, a)] = c;
                    neighbors[a].push_back(b), neighbors[b].push_back(a);
                }
            }
            printf("%I64d\n", f(neighbors));
        }
    }
    


    9년 전
5개의 댓글이 있습니다.
  • JongMan
    JongMan

    각 테스트 케이스마다 Link 초기화를 안하셨네요.


    9년 전 link
  • coldradio
    coldradio

    감사합니다.~^^
    근데 Link.clear();를 main의 while문 아래에 추가하고 했는데도 오답이 뜨네요.. OTL.


    9년 전 link
  • JongMan
    JongMan

    좀더 자세히 보니 다익스트라를 잘못 구현하셨네요. 큐에 넣고 나서 최단거리를 업데이트한다고 해서 큐에 들어 있는 원소들의 순서가 자동으로 바뀌지 않습니다. 반복문 불변식이 깨져서 오작동하게 되지요. 따라서 큐에 원소를 넣을 때 최단거리를 복사해서 넣으셔야 할겁니다.


    9년 전 link
  • coldradio
    coldradio

    앗, 생각치도 못했던 부분이네요~
    priority_queue를 좀 더 살펴보고 구현을 바꿔보겠습니다.~
    회사원이다 보니, 빨른 코멘트가 어렵네요~
    감사드려요~!~!~!~!~!~!


    9년 전 link
  • coldradio
    coldradio

    드디어 풀었네요. 감사합니다.^^


    9년 전 link
  • 정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.