반응형

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

 

1854번: K번째 최단경로 찾기

첫째 줄에 n, m, k가 주어진다. (1 ≤ n ≤ 1000, 0 ≤ m ≤ 2000000, 1 ≤ k ≤ 100) n과 m은 각각 김 조교가 여행을 고려하고 있는 도시들의 개수와, 도시 간에 존재하는 도로의 수이다. 이어지는 m개의 줄에

www.acmicpc.net

1.문제설명

백준 1854번

1번 노드에서 출발하여 다른 모든 노드까지의 K번째 최단 거리를 찾는 문제이다.

 

일반적으로

한 노드에서 다른 모든 노드까지의 최단 거리를 구할 때 다익스트라 알고리즘을 이용한다.

 

이 문제도 다익스트라 알고리즘을 응용하면 K번째 최단거리를 구할 수 있다.

 

 


 

2.접근방법[알고리즘]

 

이 문제에서 가장 헷갈리는 점은 

기존 최단거리를 구하는 다익스트라 알고리즘과 다르게

방문한 노드를 재방문해도 된다는 점이다.

 

방문한 노드를 재방문해도 되도록 코드를 구성하면

계속 무한루프에 빠지지 않을까?

 

이를 해결하기 위해 

방문 여부 대신 다른 조건을 추가해주어야 한다.

 

 

백준 1854번

 

그림에 잘 보면 2->3->5->2가 계속 무한으로 순환할 수 있다.

 

노드를 방문하는 우선순위큐와 다르게

 

특정 노드까지 거리를 저장하는 우선순위큐 배열을 따로 두어서

 

K번째 최단 거리까지 구했다면 더 이상 순환하지 않도록 코드를 구현해야 한다.

 

 

 

 

 

 

 

 

 


 

3.문제풀이코드 C++

#include <bits/stdc++.h>
using namespace std;

int n, m, k;
struct Edge {
	int x;
	long long val;
	bool operator<(const Edge& b) const {
		return val > b.val;
	}
};

vector<pair<int, int> > graph[1001];
priority_queue<int> Node[1001];
priority_queue<Edge> Q;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m >> k;

	for (int i = 0; i < m; i++) {
		int a, b, c;
		cin >> a >> b >> c;
		graph[a].push_back({ b,c });
	}

	Node[1].push(0);
	Q.push({ 1,0 });

	while (!Q.empty()) {
		int x = Q.top().x;
		int val = Q.top().val;
		Q.pop();

		for (int i = 0; i < graph[x].size(); i++) {
			int nx = graph[x][i].first;
			int nd = graph[x][i].second + val;

			if (Node[nx].size() < k) {
				Node[nx].push(nd);
				Q.push({ nx,nd });
			}
			else {
				if (Node[nx].top() > nd) {
					Node[nx].pop();
					Node[nx].push(nd);
					Q.push({ nx,nd });
				}
			}
		}
	}

	for (int i = 1; i <= n; i++) {
		if (Node[i].size() < k) {
			cout << -1 << '\n';
		}
		else {
			cout << Node[i].top() << '\n';
		}
	}


	return 0;
}

백준 1854번

반응형
반응형

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

 

11779번: 최소비용 구하기 2

첫째 줄에 도시의 개수 n(1≤n≤1,000)이 주어지고 둘째 줄에는 버스의 개수 m(1≤m≤100,000)이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스

www.acmicpc.net

#include <bits/stdc++.h>
using namespace std;

int n, m, st, en;

pair<int, int> dist[1001]; //거리 , 이전노드 저장 

vector<pair<int, int> > v[1001];

struct Node {
	int x, ex ,d;
	bool operator<(const Node& b)const {
		return d > b.d;
	}
};

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);


	memset(dist, 0x3f, sizeof(dist));

	cin >> n >> m;
	for (int i = 0; i < m; i++) {
		int a, b, c;
		cin >> a >> b >> c;
		v[a].push_back({ b, c });
	}

	cin >> st >> en;
	priority_queue<Node> Q;
	Q.push({ st,-1,0 });

	vector<int> ans;


	while (!Q.empty()) {
		int x = Q.top().x;
		int ex = Q.top().ex;
		int d = Q.top().d;
		Q.pop();

		if (dist[x].first <= d) continue;

		dist[x].first = d;
		dist[x].second = ex;


		if (x == en) {
			int a = en;

			while (a != -1) {
				ans.push_back(a);
				a = dist[a].second;
			}

			cout << d << '\n';
			cout << ans.size() << '\n';

			for (int i = ans.size() - 1; i >= 0; i--) {
				cout << ans[i] << ' ';
			}
			return 0;
		}


		for (int i = 0; i < v[x].size(); i++) {
			int nx = v[x][i].first;
			int nd = d + v[x][i].second;

			if (dist[nx].first > nd) {
				Q.push({ nx,x,nd });
			}
		}
	}



	return 0;
}

백준 11779번

 

반응형
반응형

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 <bits/stdc++.h>
using namespace std;

int ans[20001], v, e, st;

struct Node {
	int n, d;

	bool operator<(const Node& b) const {
		return d > b.d;
	}
};

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	fill(ans, ans + 20001, -1);

	cin >> v >> e;
	cin >> st;

	vector<pair<int, int> > m[20001];

	for (int i = 0; i < e; i++) {
		int a, b, c;
		cin >> a >> b >> c;
		m[a].push_back({ b,c });
	}

	priority_queue<Node> Q;
	Q.push({ st,0 });

	while (!Q.empty()) {
		int cur_node = Q.top().n;
		int cur_dist = Q.top().d;
		Q.pop();

		if (ans[cur_node] == -1) {
			ans[cur_node] = cur_dist;

			for (int i = 0; i < m[cur_node].size(); i++) {
				int nx = m[cur_node][i].first;
				if (ans[nx] == -1) {
					int nd = m[cur_node][i].second + cur_dist;
					Q.push({ nx,nd });
				}
			}
		}
	}


	for (int i = 1; i <= v; i++) {
		if (ans[i] == -1) cout << "INF\n";
		else cout << ans[i] << '\n';
	}


	return 0;
}

우선순위큐 최소힙을 이용해

다익스트라 알고리즘으로 풀 수 있다.

1753번 최단경로 메모리 및 시간

 

반응형

+ Recent posts