# 다익스트라 # priority queue
기본적인 다익스트라 알고리즘에서는 1에서 출발하여 i도시 까지 도착한 최단거리 하나만 저장하면 되지만,
이 문제는 조금 응용하여 버려지는 거리(최단 거리가 아닌)값 들도 나중에 사용될 수 있기 때문에 저장한다.
즉, update부분에서 모든 경로의 거리에 대해서 저장해야한다.
저장할때 매 k번쨰 최단거리 즉 가장 최소값만 알면되기 때문에 priority_queue를 이용한다.
# 실수 했던 점
순환을 할 수 있다는 것을 생각하지 못했다.(4% 쯤에서 터짐^^)
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <climits> #define MAX 1005 #define INF 2123456789 #define MOD 1000000007 #pragma warning(disable:4996) using namespace std; typedef pair<int,int> pi; typedef long long ll; int n,m,k,a,b,c,st=1; int mem[MAX]; bool visit[MAX]; priority_queue<int,vector<int>,greater<int>> pq[MAX]; vector<pi> v[MAX]; int getmin() // 기본적인 다익스트라와 동일 { int ret=-1,mx=INF; for(int i=1;i<=n;i++) if(!visit[i]&&mem[i]<mx) ret=i,mx=mem[i]; return ret; } void update() { for(int i=0;i<v[st].size();i++) { int next=v[st][i].first; int nsum=v[st][i].second+mem[st]; pq[next].push(nsum); // 기본적인 다익스트라와는 달리 모든 경우에 대해서 priority queue로 저장한다. if(mem[next]>nsum) mem[next]=nsum; } } void djk() // 기본적인 다익스트라 { while(1) { st=getmin(); if(st==-1)break; visit[st]=true; update(); } } int main(void) { scanf("%d%d%d",&n,&m,&k); fill_n(&mem[0],MAX,INF); mem[st]=0,pq[st].push(0); // 처음 1에서 1로 갔을때 경우 0을 추가해준다. for(int i=0;i<m;i++) { scanf("%d%d%d",&a,&b,&c); v[a].push_back({b,c}); } for(int i=0;i<k;i++) { djk(); if(i!=k-1) { fill_n(&mem[0],MAX,INF); fill_n(&visit[0],MAX,0); for(int i=1;i<=n;i++) // priority queue의 제일 작은 값을 제거한다음. // 다익스트라를 다시 시도한다.(경로가 순환인 경우 떄문에) ->4%쯤에 오류 발생 { if(!pq[i].empty())pq[i].pop(); if(!pq[i].empty())mem[i]=pq[i].top(); } } } for(int i=1;i<=n;i++) if(pq[i].empty()) printf("-1\n"); else printf("%d\n",pq[i].top()); return 0; }
'IT > BOJ' 카테고리의 다른 글
백준(BOJ) 1097 마법단어 ** (0) | 2018.08.01 |
---|---|
백준(BOJ) 15897 잘못 구현한 에라토스테네스의 체 (0) | 2018.07.31 |
백준(BOJ) 2213 트리의 독립집합 ** (0) | 2018.07.25 |
백준(BOJ) 5626 제단 ** (0) | 2018.07.22 |
백준(BOJ) 1799 비숍 ** (0) | 2018.07.21 |