C# 백준 알고리즘

C# 백준 1916 최소비용 구하기

프로핌 2024. 3. 12. 15:26

최소비용 구하기

시간 제한메모리 제한제출정답맞힌 사람정답 비율
0.5 초 128 MB 90951 29559 19497 32.378%

문제

N개의 도시가 있다. 그리고 한 도시에서 출발하여 다른 도시에 도착하는 M개의 버스가 있다. 우리는 A번째 도시에서 B번째 도시까지 가는데 드는 버스 비용을 최소화 시키려고 한다. A번째 도시에서 B번째 도시까지 가는데 드는 최소비용을 출력하여라. 도시의 번호는 1부터 N까지이다.

입력

첫째 줄에 도시의 개수 N(1 ≤ N ≤ 1,000)이 주어지고 둘째 줄에는 버스의 개수 M(1 ≤ M ≤ 100,000)이 주어진다. 그리고 셋째 줄부터 M+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가 주어진다. 그리고 그 다음에는 도착지의 도시 번호가 주어지고 또 그 버스 비용이 주어진다. 버스 비용은 0보다 크거나 같고, 100,000보다 작은 정수이다.

그리고 M+3째 줄에는 우리가 구하고자 하는 구간 출발점의 도시번호와 도착점의 도시번호가 주어진다. 출발점에서 도착점을 갈 수 있는 경우만 입력으로 주어진다.

출력

첫째 줄에 출발 도시에서 도착 도시까지 가는데 드는 최소 비용을 출력한다.

 

 

예제 입력 1

5
8
1 2 2
1 3 3
1 4 1
1 5 10
2 4 2
3 4 1
3 5 1
4 5 3
1 5

예제 출력 1

4

 

 

 

다익스트라 알고리즘의 대표적인 기본 문제이다.

다익스트라 알고리즘을 구현하는 대표적인 방법이 2개가 있는데 하나는 선형탐색 또 하나는 우선순위큐로 구하는것이다.

선형탐색은 말 그대로 현재 최단경로가 있다면 인접 노드들을 다 검사하기 때문에 최소 n²의 시간복잡도가 생겨서 주어지는 정점과 간선들이 많아지면 메모리초과 그리고 시간초과로 문제를 못풀게되고 그래서 잘 쓰지도 않는다.

 

그래서 다익스트라 문제는 대부분 아니면 거의 우선순위큐로 문제를 풀며 우선순위큐는 최악의 상황이여도 (n log n) 시간복잡도를 가져서 대부분 문제가 풀린다고 볼수있다.

 

하지만 C#은 우선순위큐가 구현되어있긴 하지만 백준에서 지원하는 C#언어가 우선순위큐를 지원안하는 visual studio를 쓰는거 같았다. (내가 풀고 다른분들 푸는거 보면 지원 하는거 같긴하다.)

 

그래서 우선순위큐의 인터넷소스를 찾게됐고

 

https://blog.naver.com/ambidext/221285681447

 

[C#] Priority Queue (우선순위 큐)

JAVA에는 Priority Queue(우선순위 큐)가 있는데, C#에는 없는 것 같아 찾아보았습니다. 많은 사람...

blog.naver.com

 

 

이 우선순위큐 코드를 이용해서 다익스트라를 구현하고 풀게되었다.

 

코드는 우선순위큐 코드는 안올리고 우선순위큐로 푼 코드만 보여주겠다.

 

  class Program
    {
        static int n;
        static int m;
        static int INF = 100000000;
        static int[] d;
        static List<(int weight, int node)>[] maps;
        static void Main(string[] args)
        {
            string[] arr;

            n = int.Parse(Console.ReadLine());
            m = int.Parse(Console.ReadLine());
          
            maps = new List<(int weight, int node)>[n + 1];

            for (int i = 1; i < n + 1; i++)
            {
                maps[i] = new List<(int weight, int node)>();
            }

            for (int i = 0; i < m; i++)
            {
                arr = Console.ReadLine().Split();

                int v = int.Parse(arr[0]);
                int e = int.Parse(arr[1]);
                int w = int.Parse(arr[2]);

                maps[v].Add((w, e));             
            }

            arr = Console.ReadLine().Split();

            int start = int.Parse(arr[0]);
            int end = int.Parse(arr[1]);

            Dijkstra(start, end);
        
        }

        static void Dijkstra(int start, int end)
        {
            d = new int[n + 1];

            for (int i =1; i < d.Length; i++)
            {
                d[i] = INF;
            }

            d[start] = 0;

            MinHeap<Tuple<int, int>> pq = new MinHeap<Tuple<int, int>>();

            pq.Add(new Tuple<int, int>(d[start], start));

            while (pq.Count != 0)
            {
                int distance = pq.GetMin().Item1;
                int current = pq.ExtractDominating().Item2;

                if (d[current] < distance) continue;

                for (int i = 0; i < maps[current].Count; i++)
                {
                    int node = maps[current][i].node;
                    int weight = distance + maps[current][i].weight

                    if (d[node] > weight)
                    {
                        d[node] = weight;

                        pq.Add(new Tuple<int, int>(d[node], node));
                    }
                }
            }                 
            Console.WriteLine(d[end]);
        }
    }
}