ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준 1753] 최단 거리
    C 프로그래밍/BOJ 2022. 9. 15. 20:22
    728x90

    https://www.acmicpc.net/problem/1753

     

    1753번: 최단경로

    첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1 ≤ V ≤ 20,000, 1 ≤ E ≤ 300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1 ≤ K ≤ V)가

    www.acmicpc.net

    #include <cstdio>
    #include <queue>
    #include <list>
    #include <algorithm>
    int V, E;
    int K;
    int chk[20000 + 10];
    int ans[20000 + 10];
    
    using namespace std;
    
    struct _st
    {
    	int n;
    	int c;
    };
    
    struct COMP
    {
    	bool operator()(_st &a, _st &b) {
    		return a.c > b.c;	// 가중치가 작은 노드를 기준으로 탐색한다.
    	}
    };
    
    priority_queue<_st, vector<_st>, COMP> PQ;
    list<_st> adj[20000 + 10];
    
    void input(void)
    {
    	scanf("%d %d", &V, &E);
    	scanf("%d", &K);
    	for (int i = 0; i < E; i++) {
    		int u = 0; int v = 0; int w = 0;
    		scanf("%d %d %d", &u, &v, &w);
    		adj[u].push_back({ v, w });
    	}
    }
    
    
    void BFS(void)
    {
    	fill(chk + 1, chk + V + 1, 0x7fffffff);
    	
    	PQ.push({ K, 0 });	// 시작점 자신은 0을 출력한다. 
    	chk[K] = 0;
    
    	while (!PQ.empty()) {
    		_st data = PQ.top();
    		PQ.pop();
    
    		for (auto next : adj[data.n]) {
    			int nn = next.n;
    			int nc = data.c + next.c;
    			if (chk[nn] <= nc) continue;
    			chk[nn] = nc;
    			PQ.push({ nn, nc });
    		}
    	}
    }
    
    
    void output(void)
    {
    	for (int i = 1; i <= V; i++) {
    		if (chk[i] == 0x7fffffff) printf("INF\n");
    		else printf("%d\n", chk[i]);
    	}
    }
    
    
    
    int main()
    {
    	input();
    	BFS();
    	output();
    	return 0;
    }

    이 문제에서 특히 고려해야 할 점은 다음의 두 가지 이다. 

     

    1. 우선순위 큐를 활용해야 한다. 

    그냥 큐를 통해 BFS를 구현했다면 시간초과가 날 것이다. 현재 노드에서 다음 노드로 이동하고자 할 때, 두 노드를 잇는 간선의 가중치가 가장 작은 경로를 우선적으로 탐색하는 우선순위 큐를 사용해야 한다. 

     

    2. 인접 리스트를 활용해야 한다. 

    문제에서 노드의 수(V)가 20,000 까지 많아질 수 있다. 따라서 20,000 * 20,000 인접행렬을 만들면 아주 높은 확률로 메모리 초과가 날 것이다. 따라서 인접한 노드의 정보만을 저장하여 효율적인 탐색을 돕는 인접 리스트를 사용해야 한다.

     

     

    나머지 로직은 BFS 함수로 최단 거리/경로/시간 등등 구하는 것과 동일하다. 

    다만 시작 정점(K)에서 모든 정점으로의 최단 경로를 구해야 하기 때문에, 특정 노드에 도착했다고 하여 BFS를 중단하는 것이 아니라, 끝까지 돌면서 각 정점으로의 최단 경로를 구하고 그것을 chk배열에 저장해 주었다.

    이렇게 하면 마지막에 output 함수에서 for 루프 한번으로 정답을 출력할 수 있다. 

     

     

    728x90

    'C 프로그래밍 > BOJ' 카테고리의 다른 글

    [백준 2580] 스도쿠  (1) 2022.09.18
    [백준 5917] Roadblock  (0) 2022.09.15
    [백준 1655] 가운데를 말해요  (0) 2022.09.15
    [백준 17141] 연구소 2  (0) 2022.09.15
    [백준 7576, 7569] 토마토  (0) 2022.09.14

    댓글

Designed by Tistory.