본문 바로가기
Computer Science

프양연 가장 짧은 길 전부 청소 / 다익스트라

by OKOK 2018. 12. 21.

1. 다익스트라

2. 큐 사용

3. 엣지 사용

4. 힙 개념이 없어도 가능?
5. 큐를 2개 사용하는 것 보니, 다익스트라 맞음

6. 트리 개념을 인접행렬로 나타냄


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
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
 
//#define BUILDING_N_MAX 200005
//#define ROAD_M_MAX 500005
 
#define BUILDING_N_MAX 7
#define ROAD_M_MAX 7
 
#define INF 1e16
 
struct _edge {
    int start;
    int end;
    int weight;
    int priv;
}EDGE[ROAD_M_MAX * 2]; // 무방향 간선은 2개의 방향성 간선으로 처리
int to[BUILDING_N_MAX]; // 출발정점 i 간선 중 마지막 출발한 간선의 번호
 
long long dist[BUILDING_N_MAX];
long long minimumWeight[BUILDING_N_MAX];
 
int qFront, qRear;
int Q[BUILDING_N_MAX * 30];
int inQ[BUILDING_N_MAX];
 
int main(void)
{
    int T, buildingNumber, roadNumber;
 
    freopen("input.txt""r", stdin);
 
    setbuf(stdout, NULL);
    scanf("%d"&T);
 
    for (int test_case = 1; test_case <= T; test_case++)
    {
 
        long long answer = 0;
        scanf("%d %d"&buildingNumber, &roadNumber);
        for (int j = 1; j <= buildingNumber; j++) {
            // 모든 정점의 출발 기록은 아직 없으므로 -1 로 초기화
            to[j] = -1;
            // 모든 정점의 최단 거리 Distant는 최초 INF로 초기화
            dist[j] = INF;
            // 모든 정점의 weight 0 으로 초기화
            minimumWeight[j] = 0;
        }
 
        int edgePosition = 0;
        for (int i = 1; i <= roadNumber; i++) {
            int s, e, w;
            scanf("%d %d %d"&s, &e, &w);
 
            // 무방향 간선은 2개의 방향성 간선으로 처리
            ++edgePosition;
            EDGE[edgePosition].start = s;
            EDGE[edgePosition].end = e;
            EDGE[edgePosition].weight = w;
            EDGE[edgePosition].priv = to[EDGE[edgePosition].start];
            to[EDGE[edgePosition].start] = edgePosition;
 
            ++edgePosition;
            EDGE[edgePosition].start = e;
            EDGE[edgePosition].end = s;
            EDGE[edgePosition].weight = w;
            EDGE[edgePosition].priv = to[EDGE[edgePosition].start];
            to[EDGE[edgePosition].start] = edgePosition;
        }
 
        // 시작시 Q 에 1번 정점을 넣어 1번 기준으로 시작
        qFront = qRear = 0;
        Q[qFront] = 1; inQ[1= 0;
        dist[1= 0;
 
        while (qFront <= qRear) {
            // x -> y , weight 
            int x = Q[qFront++]; inQ[x] = 0;
            //  Q 에서 꺼내서 해당 정점에서 시작하는 EDGE 최단거리 확인
            for (int edgePoint = to[x]; edgePoint != -1; edgePoint = EDGE[edgePoint].priv) {
                int y = EDGE[edgePoint].end;
                int w = EDGE[edgePoint].weight;
 
                if (dist[y] > dist[x] + w) {
                    dist[y] = dist[x] + w;
                    minimumWeight[y] = w;
 
                    if (!inQ[y]) {
                        Q[++qRear] = y; inQ[y] = 1;
                    }
                }
                else if (dist[y] == dist[x] + w) {
                    // 최단 거리가 같은 경우에는 EDGE weight 더 적은 경로 선택
                    if (minimumWeight[y] > w)
                        minimumWeight[y] = w;
                }
            }
 
        }
 
        for (int k = 2; k <= buildingNumber; k++) {
            answer += minimumWeight[k];
        }
        printf("#%d %lld\n", test_case, answer);
    }
    return 0;
}
 
cs


댓글