C# Coding Test Course, Dijkstra

Hello everyone! Today, we will deeply explore how to implement Dijkstra’s algorithm using C# and how to solve algorithmic problems through it. This tutorial will provide a step-by-step explanation of the basic concepts of the algorithm, problem definition, C# code implementation, and optimization methods.

1. What is Dijkstra’s Algorithm?

Dijkstra’s algorithm is a method for finding the shortest path in a graph. It is particularly useful when the weights of all edges are greater than or equal to zero. This algorithm efficiently calculates the shortest path from a specific node to all other nodes.

The basic principle of Dijkstra’s algorithm is as follows:

  1. Initialize the distance values from the starting node. Set the distance of the starting node to 0 and all other nodes to infinity.
  2. When moving from the current node to adjacent nodes, update the distance value if the distance to reach the adjacent node through the current node is shorter.
  3. Repeat this process until all nodes are visited.
  4. Finally, output the shortest distances to each node.

2. Problem Definition

The problem we will solve together is “Finding the Shortest Path.” There is a given graph consisting of nodes and edges, and we need to find the shortest distance from a specific starting node to all other nodes.

The input for the problem is as follows:

  • First line: Number of nodes N (1 <= N <= 100,000) and number of edges M (1 <= M <= 200,000)
  • From the second line onward for M lines: Information for each edge (A, B, C), where A and B are node numbers and C is the distance between the two nodes.
  • Last line: Starting node K

The output is the shortest distance to each node. Nodes that cannot be reached are marked as “INF”.

3. Algorithm Design

To implement Dijkstra’s algorithm in C#, we can use the following libraries and data structures:

  • Priority Queue: Used for managing distance information.
  • Graph Representation: Represent the graph using an adjacency list or an adjacency matrix.
  • Distance Array: Used to store the shortest distance values for each node.

4. C# Code Implementation

First, let’s take a look at the complete code to implement Dijkstra’s algorithm in C#.


using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        int[] input = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
        int N = input[0];
        int M = input[1];

        List>[] graph = new List>[N + 1];
        for (int i = 0; i <= N; i++)
            graph[i] = new List>();

        for (int i = 0; i < M; i++)
        {
            input = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
            graph[input[0]].Add(new Tuple(input[1], input[2]));
            graph[input[1]].Add(new Tuple(input[0], input[2])); // For undirected graphs
        }

        int K = int.Parse(Console.ReadLine());
        int[] distances = Dijkstra(graph, N, K);

        for (int i = 1; i <= N; i++)
        {
            Console.WriteLine(distances[i] == int.MaxValue ? "INF" : distances[i].ToString());
        }
    }

    static int[] Dijkstra(List>[] graph, int N, int start)
    {
        int[] distances = new int[N + 1];
        for (int i = 1; i <= N; i++)
            distances[i] = int.MaxValue;
        distances[start] = 0;

        PriorityQueue priorityQueue = new PriorityQueue();
        priorityQueue.Enqueue(start, 0);

        while (priorityQueue.Count > 0)
        {
            var current = priorityQueue.Dequeue();
            int currentNode = current.Item1;
            int currentDistance = current.Item2;

            if (currentDistance > distances[currentNode]) continue;

            foreach (var edge in graph[currentNode])
            {
                int nextNode = edge.Item1;
                int weight = edge.Item2;

                if (distances[currentNode] + weight < distances[nextNode])
                {
                    distances[nextNode] = distances[currentNode] + weight;
                    priorityQueue.Enqueue(nextNode, distances[nextNode]);
                }
            }
        }

        return distances;
    }
}

5. Code Explanation

The code above implements Dijkstra’s algorithm. Let’s explain the function of each part in detail.

5.1. Main Function

The main function takes input, constructs the graph, and then calls the Dijkstra function.

  • Receives input to determine N and M.
  • Initializes the graph represented as a list for each node.
  • Constructs the graph based on the given edge information.
  • Takes the starting node K as input and calls the Dijkstra function to return the shortest distance array.
  • Outputs the shortest distance for each node. If unreachable, it displays “INF”.

5.2. Dijkstra Function

The Dijkstra function contains the core logic of the Dijkstra algorithm.

  • Initializes the distance array.
  • Uses a priority queue to store current node information and selects the node with the smallest distance.
  • Performs shortest distance updates for adjacent nodes of the current node.

6. Test Cases

Now, let’s create some test cases to verify if Dijkstra’s algorithm works correctly.

6.1. Test Case 1

Input:


5 6
1 2 2
1 3 3
2 3 1
2 4 5
3 4 2
3 5 1
1

Output:


0
2
3
5
4

6.2. Test Case 2

Input:


4 4
1 2 3
1 3 1
2 4 1
3 4 5
1

Output:


0
3
1
4

7. Summary and Optimization

In this tutorial, we implemented Dijkstra’s algorithm using C# and solved the shortest path problem. To improve the efficiency of Dijkstra’s algorithm, we can consider the following optimization methods:

  • Using a Fibonacci heap instead of a priority queue can achieve a worst-case time complexity of O(V log V).
  • Using an adjacency list for sparse graphs can save memory.

The topic covered in the next tutorial will be “Bellman-Ford Algorithm”, which is useful for finding the shortest path when negative weight edges exist. I hope this helps improve your algorithm skills! Thank you.