mojo's Blog

[백준 11779] 최소비용 구하기 2 본문

백준/Graph

[백준 11779] 최소비용 구하기 2

_mojo_ 2021. 12. 1. 23:51

문제 링크 => 11779번: 최소비용 구하기 2 (acmicpc.net)

 

11779번: 최소비용 구하기 2

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

www.acmicpc.net

 

전형적인 다익스트라 문제이다.

 

다익스트라 알고리즘을 활용하여 최소거리를 구할 수 있어야 하며 동시에 경로까지 출력해야 하는 문제이다.

경로를 추적하기 위한 배열 trace 를 이용하였다.

시작 지점으로부터 다음 지점(next)까지의 최소 거리를 Distance[next] 라고 할 때 해당 값이 update 될 때마다

현재 위치(cur)에 대해서 trace[next] = cur 을 함으로써 추적해간다.

최적의 경로를 발견했다면 아래와 같은 방법으로 정점들을 구할 수 있다.

 

trace[next] = cur 와 같은 구조로 이뤄지며 end(E)에서 start(S)까지 다음과 같이 재귀적으로 구할 수 있다.

(1) trace[E]   = x1    : 정점 갯수는 2개다.

(2) trace[x1] = x2    : 정점 갯수는 3개다.

(3) trace[x2] = x3    : 정점 갯수는 4개다.

...

(n) trace[xn-1] = S : 정점 갯수는 n+1개이고 시작지점(S)에 도달하였다.

      따라서 정점들을 출력해가면서 함수를 역으로 리턴해가면 된다.

 

 

Solution Code

 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

struct Info {
	int x;
	int distance;
};

struct Edge {
	int next_node;
	int distance;
	Edge* next;
};

struct Node {
	struct Edge* head;
};

Node node[1001];
Info heap[100001];
int trace[1001], Distance[1001];
int n, m, heap_size;

#define INF 1000000000

Edge* make_edge(int next_node, int distance) {
	Edge* e = (Edge*)malloc(sizeof(Edge));
	e->next_node = next_node;
	e->distance = distance;
	e->next = nullptr;
	return e;
}

void init() {
	struct Edge* tmp;
	for (int i = 1; i <= n; i++) {
		tmp = (Edge*)malloc(sizeof(Edge));
		tmp->next = nullptr;
		node[i].head = tmp;
	}
}

void PQ_insert(Info tmp) {
	int x;
	x = ++heap_size;
	while ((x != 1) && (heap[x / 2].distance > tmp.distance)) {
		heap[x] = heap[x / 2];
		x /= 2;
	}
	heap[x] = tmp;
}

Info PQ_delete() {
	int parent, child;
	Info temp, ret;

	parent = 1, child = 2;
	ret = heap[1], temp = heap[heap_size--];
	while (child <= heap_size) {
		if ((child < heap_size) && (heap[child].distance > heap[child + 1].distance)) child++;
		if (temp.distance <= heap[child].distance) break;
		heap[parent] = heap[child];
		parent = child;
		child *= 2;
	}

	heap[parent] = temp;
	return ret;
}

void connect_edge(Edge* head, Edge* edge) {
	if (head->next == nullptr) {
		head->next = edge;
	}
	else {
		edge->next = head->next;
		head->next = edge;
	}
}

void show_answer(int trace[], int S, int x, int cnt) {
	if (x == S) {
		printf("%d\n", cnt);
		printf("%d ", x);
		return;
	}
	show_answer(trace, S, trace[x], cnt + 1);
	printf("%d ", x);
}

void Dijkstra(int S, int E) {
	Info tmp;
	int cur, distance, next, next_distance;
	for (int i = 1; i <= n; i++)
		Distance[i] = INF;
	
	tmp.x = S, tmp.distance = 0;
	PQ_insert(tmp);
	while (heap_size) {
		tmp = PQ_delete();
		cur = tmp.x, distance = tmp.distance;
		struct Edge* e = node[cur].head;
		while (e->next) {
			e = e->next;
			next = e->next_node, next_distance = distance + e->distance;
			if (next_distance < Distance[next]) {
				Distance[next] = next_distance;
				trace[next] = cur;
				tmp.x = next, tmp.distance = next_distance;
				PQ_insert(tmp);
			}
		}
	}

	printf("%d\n", Distance[E]);
	show_answer(trace, S, E, 1);
}

int main()
{
	int i, from, to, dist, start, end;
	struct Edge* edge;
	scanf("%d", &n); // 도시의 갯수
	scanf("%d", &m); // 버스의 갯수

	init();

	for (i = 0; i < m; i++) {
		scanf("%d %d %d", &from, &to, &dist);
		edge = make_edge(to, dist);
		connect_edge(node[from].head, edge);
	}

	scanf("%d %d", &start, &end);
	Dijkstra(start, end);

	return 0;
}

 

'백준 > Graph' 카테고리의 다른 글

[백준 2611] 자동차경주  (0) 2022.01.02
[백준 11404] 플로이드  (0) 2021.12.06
[백준 23743] 방탈출  (0) 2021.11.30
[백준 11378] 열혈강호 4  (2) 2021.11.10
[백준 2056] 작업  (0) 2021.11.08
Comments