ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 1753(최단경로)
    전공/알고리즘 2020. 6. 29. 14:06

    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

     

    엄청 단순한 다익스트라 문제. 

     

    문제에서 요구하는 바가 무조건 다익스트라이다.

    근데 고비가 있었다. 이제까지 인접행렬로 문제를 풀었었기 때문에 이 문제 또한 인접행렬로 문제를 풀려고 했지만, vertex가 20,000 이므로 만약에 인접행렬로 푼다면 20000*20000 4억 메모리제한에 걸리게 된다. 

     

    따라서 인접리스트로 문제를 풀어야한다. 

     

    인접리스트를 사용하려면 vector에 대해서 좀 알아야 하는데 

    vector은 index접근도 가능하고, 뒤에 집어넣는 push_back함수도 있다. 

    이것만 인지하고 있으면 나머지는 같다.

     

     

    먼저 출발점에서 인접한 모든 점을 priority_queue에 집어넣는다. 

    가장 작은 거리를 통해서 가는 나머지 거리들을 계산 후에 그 거리를 최신화 해준다. 

     

    만약 dist(시작점 0)배열이 

     

    0 2 1 4 5 9

     

    이렇게 존재한다면 

     

    여기서 가장 작은 거리인 1 index = 2를 거쳐서 가는 경우와 그렇지 않은 경우를 비교, 만약에 더 적게 걸린다면 그 거리로 최신화 해주고 그 경우를 pq에 집어넣는다. 

     

    pq가 빌때까지 반복한다.

     

    #include<iostream>
    #include<queue>
    #include<utility>
    #include<vector>
    using namespace std;
    #define MAX 20001
    #define MAX2 300001
    
    priority_queue<pair<int, int> > pq;
    pair<int, int> p;
    vector<pair<int, int> > adj[MAX];
    int dist[MAX];
    int V, E, start, INF = 987654321, a, b, c;
    bool checked[MAX] = { false };
    
    void solve() {
    	for (int i = 0; i < adj[start].size(); i++) {
    		pq.push(make_pair(-adj[start][i].second, adj[start][i].first));
    	}
    	while (!pq.empty()) {
    		p = pq.top();
    		pq.pop();
    		if (!checked[p.second]) {
    			checked[p.second] = true;
    			for (int i = 0; i < adj[p.second].size(); i++) {
    				if (dist[adj[p.second][i].first] > dist[p.second] + adj[p.second][i].second) {
    					dist[adj[p.second][i].first] = dist[p.second] + adj[p.second][i].second;
    					pq.push(make_pair(-dist[adj[p.second][i].first], adj[p.second][i].first));
    				}
    			}
    		}
    	}
    }
    
    int main() {
    	ios_base::sync_with_stdio(false);
    	cin.tie(0);
    	cin >> V >> E >> start;
    	for (int i = 0; i < E;  i++) {
    		cin >> a >> b >> c;
    		adj[a].push_back(make_pair(b, c));
    		if (a == start) {
    			if(dist[b] == 0 || dist[b] > c)
    				dist[b] = c;
    		}
    	}
    	for (int i = 1; i <= V; i++) {
    		if (start != i && dist[i] == 0) dist[i] = INF;
    	}
    	
    
    
    	solve();
    
    	for (int i = 1; i <= V; i++) {
    		if (dist[i] == INF)
    			cout << "INF\n";
    		else
    			cout << dist[i] << "\n";
    	}
    
    }
    
    

     

     

    주의점

     

    이 문제에서는 a->b로 가는 경로가 하나가 아니다. 따라서 그것을 확인해주어야 한다. 

    받은 입력중에 최단 경로만 저장한다. 

    '전공 > 알고리즘' 카테고리의 다른 글

    백준 13549(숨바꼭질3)  (0) 2020.06.29
    백준 1916(최소비용 구하기)  (0) 2020.06.29
    백준 2665(미로만들기)  (0) 2020.06.28
    백준 1719(택배)  (0) 2020.06.28
    백준 1504(특정한 최단 경로)  (0) 2020.06.26

    댓글

Designed by Tistory.