Open In App

Approximate solution for Travelling Salesman Problem using MST

Last Updated : 08 Apr, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a 2d matrix cost[][] of size n where cost[i][j] denotes the cost of moving from city i to city j. The task is to complete a tour from city 0 (0-based index) to all other towns such that we visit each city exactly once and then return to city 0 at minimum cost.

Note: There is a difference between the Hamiltonian Cycle and TSP. The Hamiltonian cycle problem is to find if there exists a tour that visits every city exactly once. Here we know that the Hamiltonian Tour exists (because the graph is complete) and, many such tours exist, the problem is to find a minimum weight Hamiltonian Cycle. 

Examples:

Input: cost[][] = [[0, 111], [112, 0]]
Output: 223
Explanation: We can visit 0->1->0 and cost = 111 + 112 = 223.

Input: cost[][] = [[0, 1000, 5000], [5000, 0, 1000], [1000, 5000, 0]]
Output: 3000
Explanation: We can visit 0->1->2->0 and cost = 1000 + 1000 + 1000 = 3000.

We introduced Travelling Salesman Problem and discussed Naive and Dynamic Programming Solutions for the problem. Both of the solutions are infeasible. In fact, there is no polynomial time solution available for this problem as the problem is a known NP-Hard problem. There are approximate algorithms to solve the problem though. The approximate algorithms work only if the problem instance satisfies Triangle-Inequality. 

What is Triangle Inequality?

The least distant path to reach a vertex j from i is always to reach j directly from i, rather than through some other vertex k (or vertices), i.e., dis(i, j) is always less than or equal to dis(i, k) + dist(k, j). The Triangle-Inequality holds in many practical situations. 

Using Minimum Spanning Tree - 2 Approximate Algorithm

When the cost function satisfies the triangle inequality, we can design an approximate algorithm for TSP that returns a tour whose cost is never more than twice the cost of an optimal tour. The idea is to use Minimum Spanning Tree (MST). Following is the MST based algorithm. 

Algorithm: 

  1. Let 1 be the starting and ending point for salesman. 
  2. Construct MST from with 1 as root using Prim's Algorithm.
  3. List vertices visited in preorder walk of the constructed MST and add 1 at the end. 

Let us consider the following example. The first diagram is the given graph. The second diagram shows MST constructed with 1 as root. The preorder traversal of MST is 1-2-4-3. Adding 1 at the end gives 1-2-4-3-1 which is the output of this algorithm.

Euler1 

 MST_TSP 

In this case, the approximate algorithm produces the optimal tour, but it may not produce optimal tour in all cases. 

How is algorithm 2-approximate? 

The cost of the output produced by the above algorithm is never more than twice the cost of best possible output. Let us see how is this guaranteed by the above algorithm. 

Let us define a term full walk to understand this. A full walk is lists all vertices when they are first visited in preorder, it also list vertices when they are returned after a subtree is visited in preorder. The full walk of above tree would be 1-2-1-4-1-3-1. 

Following are some important facts that prove the 2-approximateness. 

  • The cost of best possible Travelling Salesman tour is never less than the cost of MST. (The definition of MST says, it is a minimum cost tree that connects all vertices). 
  • The total cost of full walk is at most twice the cost of MST (Every edge of MST is visited at-most twice) 
  • The output of the above algorithm is less than the cost of full walk. In above algorithm, we print preorder walk as output. In preorder walk, two or more edges of full walk are replaced with a single edge. For example, 2-1 and 1-4 are replaced by 1 edge 2-4. So if the graph follows triangle inequality, then this is always true. 

From the above three statements, we can conclude that the cost of output produced by the approximate algorithm is never more than twice the cost of best possible solution. 

Below is given the implementation:

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

// function to calculate the cost of the tour
int tourCost(vector<vector<int>> &tour) {
    int cost = 0;
    for(auto edge: tour) {
        cost += edge[2];
    }
    return cost;
}

// function to find the eulerian circuit
void eulerianCircuit(vector<vector<vector<int>>> &adj, int u, 
        vector<int> &tour, vector<bool> &visited, int parent) {
    visited[u] = true;
    tour.push_back(u);

    for(auto neighbor: adj[u]) {
        int v = neighbor[0];
        if(v == parent) continue;

        if(!visited[v]) {
            eulerianCircuit(adj, v, tour, visited, u);
        }
    }
}

// function to find the minimum spanning tree
vector<vector<int>> findMST(
    vector<vector<vector<int>>> &adj, int &mstCost) {
    int n = adj.size();

    // to marks the visited nodes
    vector<bool> visited(n, false);

    // stores edges of minimum spanning tree
    vector<vector<int>> mstEdges ;

    priority_queue<vector<int>, 
        vector<vector<int>>, greater<vector<int>>> pq;

    pq.push({0, 0, -1});

    while(!pq.empty()) {
        vector<int> current = pq.top();
        pq.pop();

        int u = current[1];
        int weight = current[0];
        int parent = current[2];

        if(visited[u]) continue;

        mstCost += weight;
        visited[u] = true;

        if(parent != -1) {
            mstEdges.push_back({u, parent, weight});
        }

        for(auto neighbor: adj[u]) {
            int v = neighbor[0];
            if(v == parent) continue;
            int w = neighbor[1];

            if(!visited[v]) {
                pq.push({w, v, u});
            }
        }
    }
    return mstEdges;
}

// function to implement approximate TSP
vector<vector<int>> approximateTSP(
        vector<vector<vector<int>>> &adj) {
    int n = adj.size();

    // to store the cost of minimum spanning tree
    int mstCost = 0;

    // stores edges of minimum spanning tree
    vector<vector<int>> mstEdges = findMST(adj, mstCost);

    // to mark the visited nodes
    vector<bool> visited(n, false);

    // create adjacency list for mst
    vector<vector<vector<int>>> mstAdj(n);
    for(auto e: mstEdges) {
        mstAdj[e[0]].push_back({e[1], e[2]});
        mstAdj[e[1]].push_back({e[0], e[2]});
    }

    // to store the eulerian tour
    vector<int> tour;
    eulerianCircuit(mstAdj, 0, tour, visited, -1);

    // add the starting node to the tour
    tour.push_back(0);

    // to store the final tour path
    vector<vector<int>> tourPath;

    for(int i = 0; i < tour.size() - 1; i++) {
        int u = tour[i];
        int v = tour[i + 1];
        int weight = 0;

        // find the weight of the edge u -> v
        for(auto neighbor: adj[u]) {
            if(neighbor[0] == v) {
                weight = neighbor[1];
                break;
            }
        }

        // add the edge to the tour path
        tourPath.push_back({u, v, weight});
    }

    return tourPath;
}

// function to calculate if the 
// triangle inequality is violated
bool triangleInequality(vector<vector<vector<int>>> &adj) {
    int n = adj.size();

    // Sort each adjacency list based 
    // on the weight of the edges
    for(int i = 0; i < n; i++) {
        sort(adj[i].begin(), adj[i].end(), 
            [](const vector<int> &a, const vector<int> &b) {
            return a[1] < b[1];
        });
    }

    // check triangle inequality for each 
    // triplet of nodes (u, v, w)
    for(int u = 0; u < n; u++) {
        for(auto x: adj[u]) {
            int v = x[0];
            int costUV = x[1];

            for(auto y: adj[v]) {
                int w = y[0];
                int costVW = y[1];

                // check if there is an edge u -> w
                // check the triangle inequality
                for(auto z: adj[u]) {
                    if(z[0] == w) {
                        int costUW = z[1];

                        // if the triangle inequality is violated
                        if((costUV + costVW < costUW) && (u < w)) {
                            return true;
                        }
                    }
                }
            }
        }
    }

    // no violations found
    return false;
}

// function to create the adjacency list
vector<vector<vector<int>>> createList(
                    vector<vector<int>> &cost) {
    int n = cost.size();

    // to store the adjacency list
    vector<vector<vector<int>>> adj(n);

    for(int u = 0; u < n; u++) {
        for(int v = 0; v < n; v++) {

            // if there is no edge between u and v
            if(cost[u][v] == 0) continue;

            // add the edge to the adjacency list
            adj[u].push_back({v, cost[u][v]});
        }
    }

    return adj;
}

// function to solve the travelling salesman problem
int tsp(vector<vector<int>> &cost) {

    // create the adjacency list
    vector<vector<vector<int>>> adj = createList(cost);

    /* check for triangle inequality violations
    if(triangleInequality(adj)) {
        cout << "Triangle Inequality Violation" << endl;
        return -1;
    } */

    // construct the travelling salesman tour
    vector<vector<int>> tspTour = approximateTSP(adj);

    // calculate the cost of the tour
    int tspCost = tourCost(tspTour);

    return tspCost;

}

int main(){
    vector<vector<int>> cost = {
        {0, 1000, 5000},
        {5000, 0, 1000},
        {1000, 5000, 0}
    };

    cout << tsp(cost);
    return 0;
}
Java
// function to calculate the cost of the tour
import java.util.*;
 
class GfG {
 
    // function to calculate the cost of the tour
    static int tourCost(int[][] tour) {
        int cost = 0;
        for (int[] edge : tour) {
            cost += edge[2];
        }
        return cost;
    }
 
    // function to find the eulerian circuit
    static void eulerianCircuit(int[][][] adj, int u, ArrayList<Integer> tour, boolean[] visited, int parent) {
        visited[u] = true;
        tour.add(u);
 
        for (int[] neighbor : adj[u]) {
            int v = neighbor[0];
            if (v == parent) continue;
        
            if(!visited[v]) {
                eulerianCircuit(adj, v, tour, visited, u);
            }
        }
    }
 
    // function to find the minimum spanning tree
    static ArrayList<int[]> findMST(int[][][] adj, int[] mstCost) {
        int n = adj.length;
 
        // to marks the visited nodes
        boolean[] visited = new boolean[n];
 
        // stores edges of minimum spanning tree
        ArrayList<int[]> mstEdges = new ArrayList<>();
 
        PriorityQueue<int[]> pq = new PriorityQueue<>(new Comparator<int[]>() {
            public int compare(int[] a, int[] b) {
                return a[0] - b[0];
            }
        });
 
        pq.add(new int[]{0, 0, -1});
 
        while (!pq.isEmpty()) {
            int[] current = pq.poll();
 
            int u = current[1];
            int weight = current[0];
            int parent = current[2];
 
            if (visited[u]) continue;
 
            mstCost[0] += weight;
            visited[u] = true;
 
            if (parent != -1) {
                mstEdges.add(new int[]{u, parent, weight});
            }
 
            for (int[] neighbor : adj[u]) {
                int v = neighbor[0];
                if (v == parent) continue;
                int w = neighbor[1];
 
                if (!visited[v]) {
                    pq.add(new int[]{w, v, u});
                }
            }
        }
        return mstEdges;
    }
 
    // function to implement approximate TSP
    static ArrayList<int[]> approximateTSP(int[][][] adj) {
        int n = adj.length;
 
        // to store the cost of minimum spanning tree
        int mstCost = 0;
 
        // stores edges of minimum spanning tree
        ArrayList<int[]> mstEdges = findMST(adj, new int[]{mstCost});
 
        // to mark the visited nodes
        boolean[] visited = new boolean[n];
 
        // create adjacency list for mst
        ArrayList<ArrayList<int[]>> mstAdjList = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            mstAdjList.add(new ArrayList<>());
        }
        for (int[] e : mstEdges) {
            mstAdjList.get(e[0]).add(new int[]{e[1], e[2]});
            mstAdjList.get(e[1]).add(new int[]{e[0], e[2]});
        }
 
        // convert mstAdjList to int[][][] mstAdj
        int[][][] mstAdj = new int[n][][];
        for (int i = 0; i < n; i++) {
            ArrayList<int[]> list = mstAdjList.get(i);
            mstAdj[i] = list.toArray(new int[list.size()][]);
        }
 
        // to store the eulerian tour
        ArrayList<Integer> tour = new ArrayList<>();
        eulerianCircuit(mstAdj, 0, tour, visited, -1);
 
        // add the starting node to the tour
        tour.add(0);
 
        // to store the final tour path
        ArrayList<int[]> tourPath = new ArrayList<>();
 
        for (int i = 0; i < tour.size() - 1; i++) {
            int u = tour.get(i);
            int v = tour.get(i + 1);
            int weight = 0;
 
            // find the weight of the edge u -> v
            for (int[] neighbor : adj[u]) {
                if (neighbor[0] == v) {
                    weight = neighbor[1];
                    break;
                }
            }
 
            // add the edge to the tour path
            tourPath.add(new int[]{u, v, weight});
        }
 
        return tourPath;
    }
 
    // function to calculate if the 
    // triangle inequality is violated
    static boolean triangleInequality(int[][][] adj) {
        int n = adj.length;
 
        // Sort each adjacency list based 
        // on the weight of the edges
        for (int i = 0; i < n; i++) {
            Arrays.sort(adj[i], new Comparator<int[]>() {
                public int compare(int[] a, int[] b) {
                    return a[1] - b[1];
                }
            });
        }
 
        // check triangle inequality for each 
        // triplet of nodes (u, v, w)
        for (int u = 0; u < n; u++) {
            for (int[] x : adj[u]) {
                int v = x[0];
                int costUV = x[1];
 
                for (int[] y : adj[v]) {
                    int w = y[0];
                    int costVW = y[1];
 
                    // check if there is an edge u -> w
                    // check the triangle inequality
                    for (int[] z : adj[u]) {
                        if (z[0] == w) {
                            int costUW = z[1];
 
                            // if the triangle inequality is violated
                            if ((costUV + costVW < costUW) && (u < w)) {
                                return true;
                            }
                        }
                    }
                }
            }
        }
 
        // no violations found
        return false;
    }
 
    // function to create the adjacency list
    static int[][][] createList(int[][] cost) {
        int n = cost.length;
 
        // to store the adjacency list
        ArrayList<ArrayList<int[]>> adjList = new ArrayList<>();
 
        for (int u = 0; u < n; u++) {
            adjList.add(new ArrayList<>());
            for (int v = 0; v < n; v++) {
 
                // if there is no edge between u and v
                if (cost[u][v] == 0) continue;
 
                // add the edge to the adjacency list
                adjList.get(u).add(new int[]{v, cost[u][v]});
            }
        }
 
        int[][][] adj = new int[n][][];
        for (int u = 0; u < n; u++) {
            ArrayList<int[]> list = adjList.get(u);
            adj[u] = list.toArray(new int[list.size()][]);
        }
 
        return adj;
    }
 
    // function to solve the travelling salesman problem
    static int tsp(int[][] cost) {
 
        // create the adjacency list
        int[][][] adj = createList(cost);
 
        /* check for triangle inequality violations
        if(triangleInequality(adj)) {
            System.out.println("Triangle Inequality Violation");
            return -1;
        } */
 
        // construct the travelling salesman tour
        ArrayList<int[]> tspTour = approximateTSP(adj);
 
        // calculate the cost of the tour
        int tspCost = tourCost(convertListTo2DArray(tspTour));
 
        return tspCost;
    }
 
    // helper function to convert ArrayList<int[]> to int[][]
    static int[][] convertListTo2DArray(ArrayList<int[]> list) {
        int[][] arr = new int[list.size()][];
        for (int i = 0; i < list.size(); i++) {
            arr[i] = list.get(i);
        }
        return arr;
    }
 
    public static void main(String[] args) {
        int[][] cost = {
            {0, 1000, 5000},
            {5000, 0, 1000},
            {1000, 5000, 0}
        };
 
        System.out.println(tsp(cost));
    }
}
Python
# function to calculate the cost of the tour
def tourCost(tour):
    cost = 0
    for edge in tour:
        cost += edge[2]
    return cost

# function to find the eulerian circuit
def eulerianCircuit(adj, u, tour, visited, parent):
    visited[u] = True
    tour.append(u)
 
    for neighbor in adj[u]:
        v = neighbor[0]
        if v == parent:
            continue
        
        if visited[v] == False:
            eulerianCircuit(adj, v, tour, visited, u)
 
# function to find the minimum spanning tree
import heapq
def findMST(adj, mstCost):
    n = len(adj)
 
    # to marks the visited nodes
    visited = [False] * n
 
    # stores edges of minimum spanning tree
    mstEdges = []
 
    pq = []
    heapq.heappush(pq, [0, 0, -1])
 
    while pq:
        current = heapq.heappop(pq)
 
        u = current[1]
        weight = current[0]
        parent = current[2]
 
        if visited[u]:
            continue
 
        mstCost[0] += weight
        visited[u] = True
 
        if parent != -1:
            mstEdges.append([u, parent, weight])
 
        for neighbor in adj[u]:
            v = neighbor[0]
            if v == parent:
                continue
            w = neighbor[1]
 
            if not visited[v]:
                heapq.heappush(pq, [w, v, u])
    return mstEdges
 
# function to implement approximate TSP
def approximateTSP(adj):
    n = len(adj)
 
    # to store the cost of minimum spanning tree
    mstCost = [0]
 
    # stores edges of minimum spanning tree
    mstEdges = findMST(adj, mstCost)
 
    # to mark the visited nodes
    visited = [False] * n
 
    # create adjacency list for mst
    mstAdj = [[] for _ in range(n)]
    for e in mstEdges:
        mstAdj[e[0]].append([e[1], e[2]])
        mstAdj[e[1]].append([e[0], e[2]])
 
    # to store the eulerian tour
    tour = []
    eulerianCircuit(mstAdj, 0, tour, visited, -1)
 
    # add the starting node to the tour
    tour.append(0)
 
    # to store the final tour path
    tourPath = []
 
    for i in range(len(tour) - 1):
        u = tour[i]
        v = tour[i + 1]
        weight = 0
 
        # find the weight of the edge u -> v
        for neighbor in adj[u]:
            if neighbor[0] == v:
                weight = neighbor[1]
                break
 
        # add the edge to the tour path
        tourPath.append([u, v, weight])
 
    return tourPath
 
# function to calculate if the 
# triangle inequality is violated
def triangleInequality(adj):
    n = len(adj)
 
    # Sort each adjacency list based 
    # on the weight of the edges
    for i in range(n):
        adj[i].sort(key=lambda a: a[1])
 
    # check triangle inequality for each 
    # triplet of nodes (u, v, w)
    for u in range(n):
        for x in adj[u]:
            v = x[0]
            costUV = x[1]
            for y in adj[v]:
                w = y[0]
                costVW = y[1]
                for z in adj[u]:
                    if z[0] == w:
                        costUW = z[1]
                        if (costUV + costVW < costUW) and (u < w):
                            return True
    # no violations found
    return False
 
# function to create the adjacency list
def createList(cost):
    n = len(cost)
 
    # to store the adjacency list
    adj = [[] for _ in range(n)]
 
    for u in range(n):
        for v in range(n):
            # if there is no edge between u and v
            if cost[u][v] == 0:
                continue
            # add the edge to the adjacency list
            adj[u].append([v, cost[u][v]])
 
    return adj
 
# function to solve the travelling salesman problem
def tsp(cost):
 
    # create the adjacency list
    adj = createList(cost)
 
    """ check for triangle inequality violations
    if triangleInequality(adj):
        print("Triangle Inequality Violation")
        return -1
    """
 
    # construct the travelling salesman tour
    tspTour = approximateTSP(adj)
 
    # calculate the cost of the tour
    tspCost = tourCost(tspTour)
 
    return tspCost
 
if __name__ == "__main__":
    cost = [
        [0, 1000, 5000],
        [5000, 0, 1000],
        [1000, 5000, 0]
    ]
 
    print(tsp(cost))
C#
// function to calculate the cost of the tour
using System;
using System.Collections.Generic;
using System.Linq;
 
class GfG {
 
    // function to calculate the cost of the tour
    static int tourCost(int[][] tour) {
        int cost = 0;
        foreach (int[] edge in tour) {
            cost += edge[2];
        }
        return cost;
    }
 
    // function to find the eulerian circuit
    static void eulerianCircuit(int[][][] adj, int u, List<int> tour, bool[] visited, int parent) {
        visited[u] = true;
        tour.Add(u);
 
        foreach (int[] neighbor in adj[u]) {
            int v = neighbor[0];
            if (v == parent) continue;
 
            if(visited[v] == false) {
                eulerianCircuit(adj, v, tour, visited, u);
            }
        }
    }
 
    // function to find the minimum spanning tree
    static List<int[]> findMST(int[][][] adj, ref int mstCost) {
        int n = adj.Length;
 
        // to marks the visited nodes
        bool[] visited = new bool[n];
 
        // stores edges of minimum spanning tree
        List<int[]> mstEdges = new List<int[]>();
 
        SortedSet<int[]> pq = new SortedSet<int[]>(new Comparer());
        pq.Add(new int[]{0, 0, -1});
 
        while (pq.Count > 0) {
            int[] current = pq.Min;
            pq.Remove(current);
 
            int u = current[1];
            int weight = current[0];
            int parent = current[2];
 
            if (visited[u]) continue;
 
            mstCost += weight;
            visited[u] = true;
 
            if (parent != -1) {
                mstEdges.Add(new int[]{u, parent, weight});
            }
 
            foreach (int[] neighbor in adj[u]) {
                int v = neighbor[0];
                if (v == parent) continue;
                int w = neighbor[1];
 
                if (!visited[v]) {
                    pq.Add(new int[]{w, v, u});
                }
            }
        }
        return mstEdges;
    }
 
    class Comparer : IComparer<int[]> {
        public int Compare(int[] a, int[] b) {
            int cmp = a[0].CompareTo(b[0]);
            if (cmp == 0) {
                cmp = a[1].CompareTo(b[1]);
                if (cmp == 0) {
                    cmp = a[2].CompareTo(b[2]);
                }
            }
            return cmp;
        }
    }
 
    // function to implement approximate TSP
    static List<int[]> approximateTSP(int[][][] adj) {
        int n = adj.Length;
 
        // to store the cost of minimum spanning tree
        int mstCost = 0;
 
        // stores edges of minimum spanning tree
        List<int[]> mstEdges = findMST(adj, ref mstCost);
 
        // create adjacency list for mst
        List<int[]>[] mstAdj = new List<int[]>[n];
        for (int i = 0; i < n; i++) {
            mstAdj[i] = new List<int[]>();
        }
        foreach (int[] e in mstEdges) {
            mstAdj[e[0]].Add(new int[]{e[1], e[2]});
            mstAdj[e[1]].Add(new int[]{e[0], e[2]});
        }
 
        // convert mstAdj to int[][][] mstAdjArr
        int[][][] mstAdjArr = new int[n][][];
        for (int i = 0; i < n; i++) {
            mstAdjArr[i] = mstAdj[i].ToArray();
        }
 
        // to store the eulerian tour
        List<int> tour = new List<int>();
        eulerianCircuit(mstAdjArr, 0, tour, new bool[n], -1);
 
        // add the starting node to the tour
        tour.Add(0);
 
        // to store the final tour path
        List<int[]> tourPath = new List<int[]>();
 
        for (int i = 0; i < tour.Count - 1; i++) {
            int u = tour[i];
            int v = tour[i + 1];
            int weight = 0;
 
            // find the weight of the edge u -> v
            foreach (int[] neighbor in adj[u]) {
                if (neighbor[0] == v) {
                    weight = neighbor[1];
                    break;
                }
            }
 
            // add the edge to the tour path
            tourPath.Add(new int[]{u, v, weight});
        }
 
        return tourPath;
    }
 
    // function to calculate if the 
    // triangle inequality is violated
    static bool triangleInequality(int[][][] adj) {
        int n = adj.Length;
 
        // Sort each adjacency list based 
        // on the weight of the edges
        for (int i = 0; i < n; i++) {
            Array.Sort(adj[i], (a, b) => a[1].CompareTo(b[1]));
        }
 
        // check triangle inequality for each 
        // triplet of nodes (u, v, w)
        for (int u = 0; u < n; u++) {
            foreach (int[] x in adj[u]) {
                int v = x[0];
                int costUV = x[1];
 
                foreach (int[] y in adj[v]) {
                    int w = y[0];
                    int costVW = y[1];
 
                    // check if there is an edge u -> w
                    // check the triangle inequality
                    foreach (int[] z in adj[u]) {
                        if (z[0] == w) {
                            int costUW = z[1];
 
                            // if the triangle inequality is violated
                            if ((costUV + costVW < costUW) && (u < w)) {
                                return true;
                            }
                        }
                    }
                }
            }
        }
 
        // no violations found
        return false;
    }
 
    // function to create the adjacency list
    static int[][][] createList(int[][] cost) {
        int n = cost.Length;
 
        // to store the adjacency list
        List<int[]>[] adj = new List<int[]>[n];
        for (int u = 0; u < n; u++) {
            adj[u] = new List<int[]>();
            for (int v = 0; v < n; v++) {
 
                // if there is no edge between u and v
                if (cost[u][v] == 0) continue;
 
                // add the edge to the adjacency list
                adj[u].Add(new int[]{v, cost[u][v]});
            }
        }
 
        int[][][] adjArr = new int[n][][];
        for (int u = 0; u < n; u++) {
            adjArr[u] = adj[u].ToArray();
        }
        return adjArr;
    }
 
    // function to solve the travelling salesman problem
    static int tsp(int[][] cost) {
 
        // create the adjacency list
        int[][][] adj = createList(cost);
 
        /* check for triangle inequality violations
        if(triangleInequality(adj)) {
            Console.WriteLine("Triangle Inequality Violation");
            return -1;
        } */
 
        // construct the travelling salesman tour
        List<int[]> tspTour = approximateTSP(adj);
 
        // calculate the cost of the tour
        int tspCost = tourCost(tspTour.ToArray());
 
        return tspCost;
    }
 
    static void Main() {
        int[][] cost = new int[][] {
            new int[] {0, 1000, 5000},
            new int[] {5000, 0, 1000},
            new int[] {1000, 5000, 0}
        };
 
        Console.WriteLine(tsp(cost));
    }
}
JavaScript
// function to calculate the cost of the tour
function tourCost(tour) {
    let cost = 0;
    for (let i = 0; i < tour.length; i++) {
        cost += tour[i][2];
    }
    return cost;
}
 
// function to find the eulerian circuit
function eulerianCircuit(adj, u, tour, visited, parent) {
    visited[u] = true;
    tour.push(u);
 
    for (let i = 0; i < adj[u].length; i++) {
        let neighbor = adj[u][i];
        let v = neighbor[0];
        if (v === parent) continue;
 
        if(visited[v] == false) {
            eulerianCircuit(adj, v, tour, visited, u);
        }
    }
}
 
// function to find the minimum spanning tree
function findMST(adj, mstCostObj) {
    let n = adj.length;
 
    // to marks the visited nodes
    let visited = new Array(n).fill(false);
 
    // stores edges of minimum spanning tree
    let mstEdges = [];
 
    let pq = [];
    pq.push([0, 0, -1]);
    pq.sort((a, b) => a[0] - b[0]);
 
    while (pq.length > 0) {
        let current = pq.shift();
 
        let u = current[1];
        let weight = current[0];
        let parent = current[2];
 
        if (visited[u]) continue;
 
        mstCostObj.value += weight;
        visited[u] = true;
 
        if (parent !== -1) {
            mstEdges.push([u, parent, weight]);
        }
 
        for (let i = 0; i < adj[u].length; i++) {
            let neighbor = adj[u][i];
            let v = neighbor[0];
            if (v === parent) continue;
            let w = neighbor[1];
 
            if (!visited[v]) {
                pq.push([w, v, u]);
                pq.sort((a, b) => a[0] - b[0]);
            }
        }
    }
    return mstEdges;
}
 
// function to implement approximate TSP
function approximateTSP(adj) {
    let n = adj.length;
 
    // to store the cost of minimum spanning tree
    let mstCostObj = { value: 0 };
 
    // stores edges of minimum spanning tree
    let mstEdges = findMST(adj, mstCostObj);
 
    // to mark the visited nodes
    let visited = new Array(n).fill(false);
 
    // create adjacency list for mst
    let mstAdj = new Array(n);
    for (let i = 0; i < n; i++) {
        mstAdj[i] = [];
    }
    for (let i = 0; i < mstEdges.length; i++) {
        let e = mstEdges[i];
        mstAdj[e[0]].push([e[1], e[2]]);
        mstAdj[e[1]].push([e[0], e[2]]);
    }
 
    // to store the eulerian tour
    let tour = [];
    eulerianCircuit(mstAdj, 0, tour, new Array(n).fill(false), -1);
 
    // add the starting node to the tour
    tour.push(0);
 
    // to store the final tour path
    let tourPath = [];
 
    for (let i = 0; i < tour.length - 1; i++) {
        let u = tour[i];
        let v = tour[i + 1];
        let weight = 0;
 
        // find the weight of the edge u -> v
        for (let j = 0; j < adj[u].length; j++) {
            let neighbor = adj[u][j];
            if (neighbor[0] === v) {
                weight = neighbor[1];
                break;
            }
        }
 
        // add the edge to the tour path
        tourPath.push([u, v, weight]);
    }
 
    return tourPath;
}
 
// function to calculate if the 
// triangle inequality is violated
function triangleInequality(adj) {
    let n = adj.length;
 
    // Sort each adjacency list based 
    // on the weight of the edges
    for (let i = 0; i < n; i++) {
        adj[i].sort((a, b) => a[1] - b[1]);
    }
 
    // check triangle inequality for each 
    // triplet of nodes (u, v, w)
    for (let u = 0; u < n; u++) {
        for (let i = 0; i < adj[u].length; i++) {
            let x = adj[u][i];
            let v = x[0];
            let costUV = x[1];
 
            for (let j = 0; j < adj[v].length; j++) {
                let y = adj[v][j];
                let w = y[0];
                let costVW = y[1];
 
                for (let k = 0; k < adj[u].length; k++) {
                    let z = adj[u][k];
                    if (z[0] === w) {
                        let costUW = z[1];
 
                        // if the triangle inequality is violated
                        if ((costUV + costVW < costUW) && (u < w))
                            return true;
                    }
                }
            }
        }
    }
 
    // no violations found
    return false;
}
 
// function to create the adjacency list
function createList(cost) {
    let n = cost.length;
 
    // to store the adjacency list
    let adj = new Array(n);
    for (let u = 0; u < n; u++) {
        adj[u] = [];
        for (let v = 0; v < n; v++) {
            // if there is no edge between u and v
            if (cost[u][v] === 0) continue;
 
            // add the edge to the adjacency list
            adj[u].push([v, cost[u][v]]);
        }
    }
 
    return adj;
}
 
// function to solve the travelling salesman problem
function tsp(cost) {
 
    // create the adjacency list
    let adj = createList(cost);
 
    /* check for triangle inequality violations
    if(triangleInequality(adj)) {
        console.log("Triangle Inequality Violation");
        return -1;
    } */
 
    // construct the travelling salesman tour
    let tspTour = approximateTSP(adj);
 
    // calculate the cost of the tour
    let tspCost = tourCost(tspTour);
 
    return tspCost;
}
 
let cost = [
    [0, 1000, 5000],
    [5000, 0, 1000],
    [1000, 5000, 0]
];
 
console.log(tsp(cost));

Output
3000

Time Complexity: O(n ^ 3), the time complexity of triangleInequality() function is O(n ^ 3) as we are using 3 nested loops, and all other functions are working in O(n ^ 2), and O(n ^ 2 * log n) time complexity, thus the overall time complexity will be O(n ^ 3).
Space Complexity: O(n ^ 2), to store the adjacency list, and creating MST.

Using Christofides Algorithm - 1.5 Approximate Algorithm

The Christofides algorithm or Christofides–Serdyukov algorithm is an algorithm for finding approximate solutions to the travelling salesman problem, on instances where the distances form a metric space (they are symmetric and obey the triangle inequality).It is an approximation algorithm that guarantees that its solutions will be within a factor of 3/2 of the optimal solution length

Algorithm:

  • Create a minimum spanning tree T of G.
  • Let O be the set of vertices with odd degree in T. By the handshaking lemma, O has an even number of vertices.
  • Find a minimum-weight perfect matching M in the subgraph induced in G by O.
  • Combine the edges of M and T to form a connected multigraph H in which each vertex has even degree.
  • Form an Eulerian circuit in H.
  • Make the circuit found in previous step into a Hamiltonian circuit by skipping repeated vertices (shortcutting).

Below is given the implementation:

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

// function to calculate the cost of the tour
int tourCost(vector<vector<int>> &tour) {
    int cost = 0;
    for(auto edge: tour) {
        cost += edge[2];
    }
    return cost;
}

// function to find the minimum matching edges
vector<vector<int>> findMinimumMatching(
    vector<vector<vector<int>>> &adj, vector<int> &oddNodes) {

    // to store the matching edges
    vector<vector<int>> matchingEdges;

    // if there are no odd nodes
    if(oddNodes.empty()) return matchingEdges;

    // to store the candidate edges
    vector<vector<int>> candidateEdges;

    for(int i = 0; i < oddNodes.size(); i++) {
        int u = oddNodes[i];
        for(int j = i + 1; j < oddNodes.size(); j++) {
            int v = oddNodes[j];
            for(auto neighbor: adj[u]) {
                if(neighbor[0] == v) {
                    candidateEdges.push_back({u, v, neighbor[1]});
                    break;
                }
            }
        }
    }

    // sort the candidate edges based on the weight
    sort(candidateEdges.begin(), candidateEdges.end(), 
        [](const vector<int> &a, const vector<int> &b) {
        return a[2] < b[2];
    });

    // to store the matched nodes
    unordered_set<int> matched;

    // find the minimum matching edges
    for(auto e: candidateEdges) {
        if(matched.find(e[0]) == matched.end() && 
            matched.find(e[1]) == matched.end()) {
            matchingEdges.push_back(e);
            matched.insert(e[0]);
            matched.insert(e[1]);
        }
        if(matched.size() == oddNodes.size()) break;
    }

    return matchingEdges;
}

// function to find the eulerian circuit
void eulerianCircuit(vector<vector<vector<int>>> &adj, int u, 
        vector<int> &tour, vector<bool> &visited, int parent) {
    visited[u] = true;
    tour.push_back(u);

    for(auto neighbor: adj[u]) {
        int v = neighbor[0];
        if(v == parent) continue;

        if(!visited[v]) {
            eulerianCircuit(adj, v, tour, visited, u);
        }
    }
}

// function to find the minimum spanning tree
vector<vector<int>> findMST(
    vector<vector<vector<int>>> &adj, int &mstCost) {
    int n = adj.size();

    // to marks the visited nodes
    vector<bool> visited(n, false);

    // stores edges of minimum spanning tree
    vector<vector<int>> mstEdges ;

    priority_queue<vector<int>, 
        vector<vector<int>>, greater<vector<int>>> pq;

    pq.push({0, 0, -1});

    while(!pq.empty()) {
        vector<int> current = pq.top();
        pq.pop();

        int u = current[1];
        int weight = current[0];
        int parent = current[2];

        if(visited[u]) continue;

        mstCost += weight;
        visited[u] = true;

        if(parent != -1) {
            mstEdges.push_back({u, parent, weight});
        }

        for(auto neighbor: adj[u]) {
            int v = neighbor[0];
            if(v == parent) continue;
            int w = neighbor[1];

            if(!visited[v]) {
                pq.push({w, v, u});
            }
        }
    }
    return mstEdges;
}

// function to implement approximate TSP
vector<vector<int>> approximateTSP(
        vector<vector<vector<int>>> &adj) {
    int n = adj.size();

    // to store the cost of minimum spanning tree
    int mstCost = 0;

    // stores edges of minimum spanning tree
    vector<vector<int>> mstEdges = findMST(adj, mstCost);

    // to store the degree of each node
    vector<int> degrees(n, 0);

    // create adjacency list for mst
    vector<vector<vector<int>>> mstAdj(n);
    for(auto e: mstEdges) {
        mstAdj[e[0]].push_back({e[1], e[2]});
        mstAdj[e[1]].push_back({e[0], e[2]});
        degrees[e[0]]++;
        degrees[e[1]]++;
    }

    // to store nodes with odd degrees
    vector<int> oddNodes;

    // nodes with odd degrees
    for(int i = 0; i<n; i++) {
        if(degrees[i] % 2 != 0) {
            oddNodes.push_back(i);
        }
    }

    // find the minimum matching edges  
    vector<vector<int>> matchingEdges = findMinimumMatching(adj, oddNodes);

    // create a multigraph
    vector<vector<vector<int>>> multigraphAdj = mstAdj;
    for(auto e: matchingEdges) {
        multigraphAdj[e[0]].push_back({e[1], e[2]});
        multigraphAdj[e[1]].push_back({e[0], e[2]});
    }

    // to store the eulerian tour
    vector<int> tour;

    // to mark the visited nodes
    vector<bool> visited(n, false);

    eulerianCircuit(multigraphAdj, 0, tour, visited, -1);

    // add the starting node to the tour
    tour.push_back(0);
    // to store the final tour path
    vector<vector<int>> tourPath;

    for(int i = 0; i < tour.size() - 1; i++) {
        int u = tour[i];
        int v = tour[i + 1];
        int weight = 0;

        // find the weight of the edge u -> v
        for(auto neighbor: adj[u]) {
            if(neighbor[0] == v) {
                weight = neighbor[1];
                break;
            }
        }

        // add the edge to the tour path
        tourPath.push_back({u, v, weight});
    }
    return tourPath;
}

// function to calculate if the 
// triangle inequality is violated
bool triangleInequality(vector<vector<vector<int>>> &adj) {
    int n = adj.size();

    // Sort each adjacency list based 
    // on the weight of the edges
    for(int i = 0; i < n; i++) {
        sort(adj[i].begin(), adj[i].end(), 
            [](const vector<int> &a, const vector<int> &b) {
            return a[1] < b[1];
        });
    }

    // check triangle inequality for each 
    // triplet of nodes (u, v, w)
    for(int u = 0; u < n; u++) {
        for(auto x: adj[u]) {
            int v = x[0];
            int costUV = x[1];

            for(auto y: adj[v]) {
                int w = y[0];
                int costVW = y[1];

                // check if there is an edge u -> w
                // check the triangle inequality
                for(auto z: adj[u]) {
                    if(z[0] == w) {
                        int costUW = z[1];

                        // if the triangle inequality is violated
                        if((costUV + costVW < costUW) && (u < w)) {
                            return true;
                        }
                    }
                }
            }
        }
    }

    // no violations found
    return false;
}

// function to create the adjacency list
vector<vector<vector<int>>> createList(
                    vector<vector<int>> &cost) {
    int n = cost.size();

    // to store the adjacency list
    vector<vector<vector<int>>> adj(n);

    for(int u = 0; u < n; u++) {
        for(int v = 0; v < n; v++) {

            // if there is no edge between u and v
            if(cost[u][v] == 0) continue;

            // add the edge to the adjacency list
            adj[u].push_back({v, cost[u][v]});
        }
    }

    return adj;
}

// function to solve the travelling salesman problem
int tsp(vector<vector<int>> &cost) {

    // create the adjacency list
    vector<vector<vector<int>>> adj = createList(cost);

    /* check for triangle inequality violations
    if(triangleInequality(adj)) {
        cout << "Triangle Inequality Violation" << endl;
        return -1;
    }*/

    // construct the travelling salesman tour
    vector<vector<int>> tspTour = approximateTSP(adj);

    // calculate the cost of the tour
    int tspCost = tourCost(tspTour);

    return tspCost;

}

int main(){
    vector<vector<int>> cost = {
        {0, 1000, 5000},
        {5000, 0, 1000},
        {1000, 5000, 0}
    };


    cout << tsp(cost);
    return 0;
}
Java
// function to calculate the cost of the tour
import java.util.*;
 
class GfG {
 
    // function to calculate the cost of the tour
    static int tourCost(int[][] tour) {
        int cost = 0;
        for (int[] edge : tour) {
            cost += edge[2];
        }
        return cost;
    }
 
    // function to find the minimum matching edges
    static int[][] findMinimumMatching(int[][][] adj, int[] oddNodes) {
 
        // to store the matching edges
        ArrayList<int[]> matchingEdges = new ArrayList<>();
 
        // if there are no odd nodes
        if (oddNodes.length == 0) return matchingEdges.toArray(new int[0][]);
 
        // to store the candidate edges
        ArrayList<int[]> candidateEdges = new ArrayList<>();
 
        for (int i = 0; i < oddNodes.length; i++) {
            int u = oddNodes[i];
            for (int j = i + 1; j < oddNodes.length; j++) {
                int v = oddNodes[j];
                for (int[] neighbor : adj[u]) {
                    if (neighbor[0] == v) {
                        candidateEdges.add(new int[]{u, v, neighbor[1]});
                        break;
                    }
                }
            }
        }
 
        // sort the candidate edges based on the weight
        Collections.sort(candidateEdges, new Comparator<int[]>() {
            public int compare(int[] a, int[] b) {
                return a[2] - b[2];
            }
        });
 
        // to store the matched nodes
        HashSet<Integer> matched = new HashSet<>();
 
        // find the minimum matching edges
        for (int[] e : candidateEdges) {
            if (!matched.contains(e[0]) && !matched.contains(e[1])) {
                matchingEdges.add(e);
                matched.add(e[0]);
                matched.add(e[1]);
            }
            if (matched.size() == oddNodes.length) break;
        }
 
        return matchingEdges.toArray(new int[0][]);
    }
 
    // function to find the eulerian circuit
    static void eulerianCircuit(int[][][] adj, int u, ArrayList<Integer> tour, boolean[] visited, int parent) {
        visited[u] = true;
        tour.add(u);
 
        for (int[] neighbor : adj[u]) {
            int v = neighbor[0];
            if (v == parent) continue;
 
            if (!visited[v]) {
                eulerianCircuit(adj, v, tour, visited, u);
            }
        }
    }
 
    // function to find the minimum spanning tree
    static int[][] findMST(int[][][] adj, int[] mstCost) {
        int n = adj.length;
 
        // to marks the visited nodes
        boolean[] visited = new boolean[n];
 
        // stores edges of minimum spanning tree
        ArrayList<int[]> mstEdges = new ArrayList<>();
 
        PriorityQueue<int[]> pq = new PriorityQueue<>(new Comparator<int[]>() {
            public int compare(int[] a, int[] b) {
                return a[0] - b[0];
            }
        });
 
        pq.add(new int[]{0, 0, -1});
 
        while (!pq.isEmpty()) {
            int[] current = pq.poll();
 
            int u = current[1];
            int weight = current[0];
            int parent = current[2];
 
            if (visited[u]) continue;
 
            mstCost[0] += weight;
            visited[u] = true;
 
            if (parent != -1) {
                mstEdges.add(new int[]{u, parent, weight});
            }
 
            for (int[] neighbor : adj[u]) {
                int v = neighbor[0];
                if (v == parent) continue;
                int w = neighbor[1];
 
                if (!visited[v]) {
                    pq.add(new int[]{w, v, u});
                }
            }
        }
        return mstEdges.toArray(new int[0][]);
    }
 
    // function to implement approximate TSP
    static int[][] approximateTSP(int[][][] adj) {
        int n = adj.length;
 
        // to store the cost of minimum spanning tree
        int mstCost = 0;
 
        // stores edges of minimum spanning tree
        int[][] mstEdges = findMST(adj, new int[]{mstCost});
 
        // to store the degree of each node
        int[] degrees = new int[n];
 
        // create adjacency list for mst
        ArrayList<ArrayList<int[]>> mstAdjList = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            mstAdjList.add(new ArrayList<>());
        }
        for (int[] e : mstEdges) {
            mstAdjList.get(e[0]).add(new int[]{e[1], e[2]});
            mstAdjList.get(e[1]).add(new int[]{e[0], e[2]});
            degrees[e[0]]++;
            degrees[e[1]]++;
        }
 
        // to store nodes with odd degrees
        ArrayList<Integer> oddNodesList = new ArrayList<>();
 
        // nodes with odd degrees
        for (int i = 0; i < n; i++) {
            if (degrees[i] % 2 != 0) {
                oddNodesList.add(i);
            }
        }
 
        int[] oddNodes = new int[oddNodesList.size()];
        for (int i = 0; i < oddNodesList.size(); i++) {
            oddNodes[i] = oddNodesList.get(i);
        }
 
        // find the minimum matching edges  
        int[][] matchingEdges = findMinimumMatching(adj, oddNodes);
 
        // create a multigraph
        int[][][] multigraphAdj = new int[n][][];
        // initialize multigraphAdj with mstAdjList data
        for (int i = 0; i < n; i++) {
            ArrayList<int[]> list = mstAdjList.get(i);
            multigraphAdj[i] = list.toArray(new int[list.size()][]);
        }
        for (int[] e : matchingEdges) {
            // add edge e[0] -> e[1]
            {
                ArrayList<int[]> list = new ArrayList<>(Arrays.asList(multigraphAdj[e[0]]));
                list.add(new int[]{e[1], e[2]});
                multigraphAdj[e[0]] = list.toArray(new int[list.size()][]);
            }
            // add edge e[1] -> e[0]
            {
                ArrayList<int[]> list = new ArrayList<>(Arrays.asList(multigraphAdj[e[1]]));
                list.add(new int[]{e[0], e[2]});
                multigraphAdj[e[1]] = list.toArray(new int[list.size()][]);
            }
        }
 
        // to store the eulerian tour
        ArrayList<Integer> tour = new ArrayList<>();
 
        // to mark the visited nodes
        boolean[] visited = new boolean[n];
 
        eulerianCircuit(multigraphAdj, 0, tour, visited, -1);
 
        // add the starting node to the tour
        tour.add(0);
        // to store the final tour path
        ArrayList<int[]> tourPath = new ArrayList<>();
 
        for (int i = 0; i < tour.size() - 1; i++) {
            int u = tour.get(i);
            int v = tour.get(i + 1);
            int weight = 0;
 
            // find the weight of the edge u -> v
            for (int[] neighbor : adj[u]) {
                if (neighbor[0] == v) {
                    weight = neighbor[1];
                    break;
                }
            }
 
            // add the edge to the tour path
            tourPath.add(new int[]{u, v, weight});
        }
 
        return tourPath.toArray(new int[0][]);
    }
 
    // function to calculate if the 
    // triangle inequality is violated
    static boolean triangleInequality(int[][][] adj) {
        int n = adj.length;
 
        // Sort each adjacency list based 
        // on the weight of the edges
        for (int i = 0; i < n; i++) {
            Arrays.sort(adj[i], new Comparator<int[]>() {
                public int compare(int[] a, int[] b) {
                    return a[1] - b[1];
                }
            });
        }
 
        // check triangle inequality for each 
        // triplet of nodes (u, v, w)
        for (int u = 0; u < n; u++) {
            for (int[] x : adj[u]) {
                int v = x[0];
                int costUV = x[1];
 
                for (int[] y : adj[v]) {
                    int w = y[0];
                    int costVW = y[1];
 
                    // check if there is an edge u -> w
                    // check the triangle inequality
                    for (int[] z : adj[u]) {
                        if (z[0] == w) {
                            int costUW = z[1];
 
                            // if the triangle inequality is violated
                            if ((costUV + costVW < costUW) && (u < w)) {
                                return true;
                            }
                        }
                    }
                }
            }
        }
 
        // no violations found
        return false;
    }
 
    // function to create the adjacency list
    static int[][][] createList(int[][] cost) {
        int n = cost.length;
 
        // to store the adjacency list
        ArrayList<ArrayList<int[]>> adjList = new ArrayList<>();
        for (int u = 0; u < n; u++) {
            adjList.add(new ArrayList<>());
            for (int v = 0; v < n; v++) {
 
                // if there is no edge between u and v
                if (cost[u][v] == 0) continue;
 
                // add the edge to the adjacency list
                adjList.get(u).add(new int[]{v, cost[u][v]});
            }
        }
 
        int[][][] adj = new int[n][][];
        for (int u = 0; u < n; u++) {
            ArrayList<int[]> list = adjList.get(u);
            adj[u] = list.toArray(new int[list.size()][]);
        }
 
        return adj;
    }
 
    // function to solve the travelling salesman problem
    static int tsp(int[][] cost) {
 
        // create the adjacency list
        int[][][] adj = createList(cost);
 
        /* check for triangle inequality violations
        if(triangleInequality(adj)) {
            System.out.println("Triangle Inequality Violation");
            return -1;
        } */
 
        // construct the travelling salesman tour
        int[][] tspTour = approximateTSP(adj);
 
        // calculate the cost of the tour
        int tspCost = tourCost(tspTour);
 
        return tspCost;
    }
 
    public static void main(String[] args) {
        int[][] cost = {
            {0, 1000, 5000},
            {5000, 0, 1000},
            {1000, 5000, 0}
        };
 
 
        System.out.println(tsp(cost));
    }
}
Python
# function to calculate the cost of the tour
def tourCost(tour):
    cost = 0
    for edge in tour:
        cost += edge[2]
    return cost

# function to find the minimum matching edges
def findMinimumMatching(adj, oddNodes):
    
    # to store the matching edges
    matchingEdges = []
    
    # if there are no odd nodes
    if not oddNodes:
        return matchingEdges
    
    # to store the candidate edges
    candidateEdges = []
    
    for i in range(len(oddNodes)):
        u = oddNodes[i]
        for j in range(i + 1, len(oddNodes)):
            v = oddNodes[j]
            for neighbor in adj[u]:
                if neighbor[0] == v:
                    candidateEdges.append([u, v, neighbor[1]])
                    break
    
    # sort the candidate edges based on the weight
    candidateEdges.sort(key=lambda a: a[2])
    
    # to store the matched nodes
    matched = set()
    
    # find the minimum matching edges
    for e in candidateEdges:
        if e[0] not in matched and e[1] not in matched:
            matchingEdges.append(e)
            matched.add(e[0])
            matched.add(e[1])
        if len(matched) == len(oddNodes):
            break
    
    return matchingEdges

# function to find the eulerian circuit
def eulerianCircuit(adj, u, tour, visited, parent):
    visited[u] = True
    tour.append(u)
    
    for neighbor in adj[u]:
        v = neighbor[0]
        if v == parent:
            continue
        if not visited[v]:
            eulerianCircuit(adj, v, tour, visited, u)

# function to find the minimum spanning tree
import heapq
def findMST(adj, mstCost):
    n = len(adj)
    
    # to marks the visited nodes
    visited = [False] * n
    
    # stores edges of minimum spanning tree
    mstEdges = []
    
    pq = []
    heapq.heappush(pq, [0, 0, -1])
    
    while pq:
        current = heapq.heappop(pq)
        
        u = current[1]
        weight = current[0]
        parent = current[2]
        
        if visited[u]:
            continue
        
        mstCost[0] += weight
        visited[u] = True
        
        if parent != -1:
            mstEdges.append([u, parent, weight])
        
        for neighbor in adj[u]:
            v = neighbor[0]
            if v == parent:
                continue
            w = neighbor[1]
            if not visited[v]:
                heapq.heappush(pq, [w, v, u])
    return mstEdges

# function to implement approximate TSP
def approximateTSP(adj):
    n = len(adj)
    
    # to store the cost of minimum spanning tree
    mstCost = [0]
    
    # stores edges of minimum spanning tree
    mstEdges = findMST(adj, mstCost)
    
    # to store the degree of each node
    degrees = [0] * n
    
    # create adjacency list for mst
    mstAdj = [[] for _ in range(n)]
    for e in mstEdges:
        mstAdj[e[0]].append([e[1], e[2]])
        mstAdj[e[1]].append([e[0], e[2]])
        degrees[e[0]] += 1
        degrees[e[1]] += 1
    
    # to store nodes with odd degrees
    oddNodes = []
    
    # nodes with odd degrees
    for i in range(n):
        if degrees[i] % 2 != 0:
            oddNodes.append(i)
    
    # find the minimum matching edges  
    matchingEdges = findMinimumMatching(adj, oddNodes)
    
    # create a multigraph
    multigraphAdj = [list(lst) for lst in mstAdj]
    for e in matchingEdges:
        multigraphAdj[e[0]].append([e[1], e[2]])
        multigraphAdj[e[1]].append([e[0], e[2]])
    
    # to store the eulerian tour
    tour = []
    
    # to mark the visited nodes
    visited = [False] * n
    
    eulerianCircuit(multigraphAdj, 0, tour, visited, -1)
    
    # add the starting node to the tour
    tour.append(0)
    # to store the final tour path
    tourPath = []
    
    for i in range(len(tour) - 1):
        u = tour[i]
        v = tour[i + 1]
        weight = 0
        
        # find the weight of the edge u -> v
        for neighbor in adj[u]:
            if neighbor[0] == v:
                weight = neighbor[1]
                break
        
        # add the edge to the tour path
        tourPath.append([u, v, weight])
    
    return tourPath

# function to calculate if the 
# triangle inequality is violated
def triangleInequality(adj):
    n = len(adj)
    
    # Sort each adjacency list based 
    # on the weight of the edges
    for i in range(n):
        adj[i].sort(key=lambda a: a[1])
    
    # check triangle inequality for each 
    # triplet of nodes (u, v, w)
    for u in range(n):
        for x in adj[u]:
            v = x[0]
            costUV = x[1]
            for y in adj[v]:
                w = y[0]
                costVW = y[1]
                for z in adj[u]:
                    if z[0] == w:
                        costUW = z[1]
                        # if the triangle inequality is violated
                        if (costUV + costVW < costUW) and (u < w):
                            return True
    # no violations found
    return False

# function to create the adjacency list
def createList(cost):
    n = len(cost)
    
    # to store the adjacency list
    adj = [[] for _ in range(n)]
    
    for u in range(n):
        for v in range(n):
            # if there is no edge between u and v
            if cost[u][v] == 0:
                continue
            # add the edge to the adjacency list
            adj[u].append([v, cost[u][v]])
    
    return adj

# function to solve the travelling salesman problem
def tsp(cost):
    
    # create the adjacency list
    adj = createList(cost)
    
    """ check for triangle inequality violations
    if triangleInequality(adj):
        print("Triangle Inequality Violation")
        return -1
    """
    
    # construct the travelling salesman tour
    tspTour = approximateTSP(adj)
    
    # calculate the cost of the tour
    tspCost = tourCost(tspTour)
    
    return tspCost

if __name__ == "__main__":
    cost = [
        [0, 1000, 5000],
        [5000, 0, 1000],
        [1000, 5000, 0]
    ]
    
    print(tsp(cost))
C#
// function to calculate the cost of the tour
using System;
using System.Collections.Generic;
 
class GfG {
 
    // function to calculate the cost of the tour
    static int tourCost(int[][] tour) {
        int cost = 0;
        foreach (int[] edge in tour) {
            cost += edge[2];
        }
        return cost;
    }
 
    // function to find the minimum matching edges
    static int[][] findMinimumMatching(int[][][] adj, int[] oddNodes) {
 
        // to store the matching edges
        List<int[]> matchingEdges = new List<int[]>();
 
        // if there are no odd nodes
        if (oddNodes.Length == 0) return matchingEdges.ToArray();
 
        // to store the candidate edges
        List<int[]> candidateEdges = new List<int[]>();
 
        for (int i = 0; i < oddNodes.Length; i++) {
            int u = oddNodes[i];
            for (int j = i + 1; j < oddNodes.Length; j++) {
                int v = oddNodes[j];
                foreach (int[] neighbor in adj[u]) {
                    if (neighbor[0] == v) {
                        candidateEdges.Add(new int[]{u, v, neighbor[1]});
                        break;
                    }
                }
            }
        }
 
        // sort the candidate edges based on the weight
        candidateEdges.Sort((a, b) => a[2].CompareTo(b[2]));
 
        // to store the matched nodes
        HashSet<int> matched = new HashSet<int>();
 
        // find the minimum matching edges
        foreach (int[] e in candidateEdges) {
            if (!matched.Contains(e[0]) && !matched.Contains(e[1])) {
                matchingEdges.Add(e);
                matched.Add(e[0]);
                matched.Add(e[1]);
            }
            if (matched.Count == oddNodes.Length) break;
        }
 
        return matchingEdges.ToArray();
    }
 
    // function to find the eulerian circuit
    static void eulerianCircuit(int[][][] adj, int u, List<int> tour, bool[] visited, int parent) {
        visited[u] = true;
        tour.Add(u);
 
        foreach (int[] neighbor in adj[u]) {
            int v = neighbor[0];
            if (v == parent) continue;
 
            if (!visited[v]) {
                eulerianCircuit(adj, v, tour, visited, u);
            }
        }
    }
 
    // function to find the minimum spanning tree
    static int[][] findMST(int[][][] adj, ref int mstCost) {
        int n = adj.Length;
 
        // to marks the visited nodes
        bool[] visited = new bool[n];
 
        // stores edges of minimum spanning tree
        List<int[]> mstEdges = new List<int[]>();
 
        SortedSet<int[]> pq = new SortedSet<int[]>(new Comparer());
 
        pq.Add(new int[]{0, 0, -1});
 
        while (pq.Count > 0) {
            int[] current = pq.Min;
            pq.Remove(current);
 
            int u = current[1];
            int weight = current[0];
            int parent = current[2];
 
            if (visited[u]) continue;
 
            mstCost += weight;
            visited[u] = true;
 
            if (parent != -1) {
                mstEdges.Add(new int[]{u, parent, weight});
            }
 
            foreach (int[] neighbor in adj[u]) {
                int v = neighbor[0];
                if (v == parent) continue;
                int w = neighbor[1];
 
                if (!visited[v]) {
                    pq.Add(new int[]{w, v, u});
                }
            }
        }
        return mstEdges.ToArray();
    }
 
    class Comparer : IComparer<int[]> {
        public int Compare(int[] a, int[] b) {
            int cmp = a[0].CompareTo(b[0]);
            if (cmp == 0) {
                cmp = a[1].CompareTo(b[1]);
                if (cmp == 0) {
                    cmp = a[2].CompareTo(b[2]);
                }
            }
            return cmp;
        }
    }
 
    // function to implement approximate TSP
    static int[][] approximateTSP(int[][][] adj) {
        int n = adj.Length;
 
        // to store the cost of minimum spanning tree
        int mstCost = 0;
 
        // stores edges of minimum spanning tree
        int[][] mstEdges = findMST(adj, ref mstCost);
 
        // to store the degree of each node
        int[] degrees = new int[n];
 
        // create adjacency list for mst
        List<int[]>[] mstAdj = new List<int[]>[n];
        for (int i = 0; i < n; i++) {
            mstAdj[i] = new List<int[]>();
        }
        foreach (int[] e in mstEdges) {
            mstAdj[e[0]].Add(new int[]{e[1], e[2]});
            mstAdj[e[1]].Add(new int[]{e[0], e[2]});
            degrees[e[0]]++;
            degrees[e[1]]++;
        }
 
        // to store nodes with odd degrees
        List<int> oddNodesList = new List<int>();
 
        // nodes with odd degrees
        for (int i = 0; i < n; i++) {
            if (degrees[i] % 2 != 0) {
                oddNodesList.Add(i);
            }
        }
 
        int[] oddNodes = oddNodesList.ToArray();
 
        // find the minimum matching edges  
        int[][] matchingEdges = findMinimumMatching(adj, oddNodes);
 
        // create a multigraph
        int[][][] multigraphAdj = new int[n][][];
 
        // initialize multigraphAdj with mstAdj
        for (int i = 0; i < n; i++) {
            multigraphAdj[i] = mstAdj[i].ToArray();
        }
 
        foreach (int[] e in matchingEdges) {
            // add edge e[0] -> e[1]
            {
                List<int[]> list = new List<int[]>(multigraphAdj[e[0]]);
                list.Add(new int[]{e[1], e[2]});
                multigraphAdj[e[0]] = list.ToArray();
            }
            // add edge e[1] -> e[0]
            {
                List<int[]> list = new List<int[]>(multigraphAdj[e[1]]);
                list.Add(new int[]{e[0], e[2]});
                multigraphAdj[e[1]] = list.ToArray();
            }
        }
 
        // to store the eulerian tour
        List<int> tour = new List<int>();
 
        // to mark the visited nodes
        bool[] visited = new bool[n];
 
        eulerianCircuit(multigraphAdj, 0, tour, visited, -1);
 
        // add the starting node to the tour
        tour.Add(0);
        // to store the final tour path
        List<int[]> tourPath = new List<int[]>();
 
        for (int i = 0; i < tour.Count - 1; i++) {
            int u = tour[i];
            int v = tour[i + 1];
            int weight = 0;
 
            // find the weight of the edge u -> v
            foreach (int[] neighbor in adj[u]) {
                if (neighbor[0] == v) {
                    weight = neighbor[1];
                    break;
                }
            }
 
            // add the edge to the tour path
            tourPath.Add(new int[]{u, v, weight});
        }
 
        return tourPath.ToArray();
    }
 
    // function to calculate if the 
    // triangle inequality is violated
    static bool triangleInequality(int[][][] adj) {
        int n = adj.Length;
 
        // Sort each adjacency list based 
        // on the weight of the edges
        for (int i = 0; i < n; i++) {
            Array.Sort(adj[i], (a, b) => a[1].CompareTo(b[1]));
        }
 
        // check triangle inequality for each 
        // triplet of nodes (u, v, w)
        for (int u = 0; u < n; u++) {
            foreach (int[] x in adj[u]) {
                int v = x[0];
                int costUV = x[1];
 
                foreach (int[] y in adj[v]) {
                    int w = y[0];
                    int costVW = y[1];
 
                    // check if there is an edge u -> w
                    // check the triangle inequality
                    foreach (int[] z in adj[u]) {
                        if (z[0] == w) {
                            int costUW = z[1];
 
                            // if the triangle inequality is violated
                            if ((costUV + costVW < costUW) && (u < w)) {
                                return true;
                            }
                        }
                    }
                }
            }
        }
 
        // no violations found
        return false;
    }
 
    // function to create the adjacency list
    static int[][][] createList(int[][] cost) {
        int n = cost.Length;
 
        // to store the adjacency list
        List<int[]>[] adj = new List<int[]>[n];
        for (int u = 0; u < n; u++) {
            adj[u] = new List<int[]>();
            for (int v = 0; v < n; v++) {
 
                // if there is no edge between u and v
                if (cost[u][v] == 0) continue;
 
                // add the edge to the adjacency list
                adj[u].Add(new int[]{v, cost[u][v]});
            }
        }
 
        int[][][] adjArr = new int[n][][];
        for (int u = 0; u < n; u++) {
            adjArr[u] = adj[u].ToArray();
        }
        return adjArr;
    }
 
    // function to solve the travelling salesman problem
    static int tsp(int[][] cost) {
 
        // create the adjacency list
        int[][][] adj = createList(cost);
 
        /* check for triangle inequality violations
        if(triangleInequality(adj)) {
            Console.WriteLine("Triangle Inequality Violation");
            return -1;
        } */
 
        // construct the travelling salesman tour
        int[][] tspTour = approximateTSP(adj);
 
        // calculate the cost of the tour
        int tspCost = tourCost(tspTour);
 
        return tspCost;
    }
 
    static void Main() {
        int[][] cost = new int[][] {
            new int[] {0, 1000, 5000},
            new int[] {5000, 0, 1000},
            new int[] {1000, 5000, 0}
        };
 
        Console.WriteLine(tsp(cost));
    }
}
JavaScript
// function to calculate the cost of the tour
function tourCost(tour) {
    let cost = 0;
    for (let edge of tour) {
        cost += edge[2];
    }
    return cost;
}
 
// function to find the minimum matching edges
function findMinimumMatching(adj, oddNodes) {
 
    // to store the matching edges
    let matchingEdges = [];
 
    // if there are no odd nodes
    if (oddNodes.length === 0) return matchingEdges;
 
    // to store the candidate edges
    let candidateEdges = [];
 
    for (let i = 0; i < oddNodes.length; i++) {
        let u = oddNodes[i];
        for (let j = i + 1; j < oddNodes.length; j++) {
            let v = oddNodes[j];
            for (let neighbor of adj[u]) {
                if (neighbor[0] === v) {
                    candidateEdges.push([u, v, neighbor[1]]);
                    break;
                }
            }
        }
    }
 
    // sort the candidate edges based on the weight
    candidateEdges.sort((a, b) => a[2] - b[2]);
 
    // to store the matched nodes
    let matched = new Set();
 
    // find the minimum matching edges
    for (let e of candidateEdges) {
        if (!matched.has(e[0]) && !matched.has(e[1])) {
            matchingEdges.push(e);
            matched.add(e[0]);
            matched.add(e[1]);
        }
        if (matched.size === oddNodes.length) break;
    }
 
    return matchingEdges;
}
 
// function to find the eulerian circuit
function eulerianCircuit(adj, u, tour, visited, parent) {
    visited[u] = true;
    tour.push(u);
 
    for (let neighbor of adj[u]) {
        let v = neighbor[0];
        if (v === parent) continue;
 
        if (!visited[v]) {
            eulerianCircuit(adj, v, tour, visited, u);
        }
    }
}
 
// function to find the minimum spanning tree
function findMST(adj, mstCostObj) {
    let n = adj.length;
 
    // to marks the visited nodes
    let visited = new Array(n).fill(false);
 
    // stores edges of minimum spanning tree
    let mstEdges = [];
 
    let pq = [];
    pq.push([0, 0, -1]);
    pq.sort((a, b) => a[0] - b[0]);
 
    while (pq.length > 0) {
        let current = pq.shift();
 
        let u = current[1];
        let weight = current[0];
        let parent = current[2];
 
        if (visited[u]) continue;
 
        mstCostObj.value += weight;
        visited[u] = true;
 
        if (parent !== -1) {
            mstEdges.push([u, parent, weight]);
        }
 
        for (let neighbor of adj[u]) {
            let v = neighbor[0];
            if (v === parent) continue;
            let w = neighbor[1];
 
            if (!visited[v]) {
                pq.push([w, v, u]);
                pq.sort((a, b) => a[0] - b[0]);
            }
        }
    }
    return mstEdges;
}
 
// function to implement approximate TSP
function approximateTSP(adj) {
    let n = adj.length;
 
    // to store the cost of minimum spanning tree
    let mstCostObj = { value: 0 };
 
    // stores edges of minimum spanning tree
    let mstEdges = findMST(adj, mstCostObj);
 
    // to store the degree of each node
    let degrees = new Array(n).fill(0);
 
    // create adjacency list for mst
    let mstAdj = new Array(n);
    for (let i = 0; i < n; i++) {
        mstAdj[i] = [];
    }
    for (let e of mstEdges) {
        mstAdj[e[0]].push([e[1], e[2]]);
        mstAdj[e[1]].push([e[0], e[2]]);
        degrees[e[0]]++;
        degrees[e[1]]++;
    }
 
    // to store nodes with odd degrees
    let oddNodes = [];
 
    // nodes with odd degrees
    for (let i = 0; i < n; i++) {
        if (degrees[i] % 2 !== 0) {
            oddNodes.push(i);
        }
    }
 
    // find the minimum matching edges  
    let matchingEdges = findMinimumMatching(adj, oddNodes);
 
    // create a multigraph
    let multigraphAdj = [];
    for (let i = 0; i < n; i++) {
        multigraphAdj.push([]);
        // copy mstAdj[i]
        for (let edge of mstAdj[i]) {
            multigraphAdj[i].push(edge.slice());
        }
    }
    for (let e of matchingEdges) {
        multigraphAdj[e[0]].push([e[1], e[2]]);
        multigraphAdj[e[1]].push([e[0], e[2]]);
    }
 
    // to store the eulerian tour
    let tour = [];
 
    // to mark the visited nodes
    let visited = new Array(n).fill(false);
 
    eulerianCircuit(multigraphAdj, 0, tour, visited, -1);
 
    // add the starting node to the tour
    tour.push(0);
    // to store the final tour path
    let tourPath = [];
 
    for (let i = 0; i < tour.length - 1; i++) {
        let u = tour[i];
        let v = tour[i + 1];
        let weight = 0;
 
        // find the weight of the edge u -> v
        for (let neighbor of adj[u]) {
            if (neighbor[0] === v) {
                weight = neighbor[1];
                break;
            }
        }
 
        // add the edge to the tour path
        tourPath.push([u, v, weight]);
    }
 
    return tourPath;
}
 
// function to calculate if the 
// triangle inequality is violated
function triangleInequality(adj) {
    let n = adj.length;
 
    // Sort each adjacency list based 
    // on the weight of the edges
    for (let i = 0; i < n; i++) {
        adj[i].sort((a, b) => a[1] - b[1]);
    }
 
    // check triangle inequality for each 
    // triplet of nodes (u, v, w)
    for (let u = 0; u < n; u++) {
        for (let x of adj[u]) {
            let v = x[0];
            let costUV = x[1];
 
            for (let y of adj[v]) {
                let w = y[0];
                let costVW = y[1];
 
                // check if there is an edge u -> w
                // check the triangle inequality
                for (let z of adj[u]) {
                    if (z[0] === w) {
                        let costUW = z[1];
 
                        // if the triangle inequality is violated
                        if ((costUV + costVW < costUW) && (u < w)) {
                            return true;
                        }
                    }
                }
            }
        }
    }
 
    // no violations found
    return false;
}
 
// function to create the adjacency list
function createList(cost) {
    let n = cost.length;
 
    // to store the adjacency list
    let adj = [];
    for (let u = 0; u < n; u++) {
        adj.push([]);
        for (let v = 0; v < n; v++) {
            // if there is no edge between u and v
            if (cost[u][v] === 0) continue;
 
            // add the edge to the adjacency list
            adj[u].push([v, cost[u][v]]);
        }
    }
 
    return adj;
}
 
// function to solve the travelling salesman problem
function tsp(cost) {
 
    // create the adjacency list
    let adj = createList(cost);
 
    /* check for triangle inequality violations
    if(triangleInequality(adj)) {
        console.log("Triangle Inequality Violation");
        return -1;
    } */
 
    // construct the travelling salesman tour
    let tspTour = approximateTSP(adj);
 
    // calculate the cost of the tour
    let tspCost = tourCost(tspTour);
 
    return tspCost;
}
 
let cost = [
    [0, 1000, 5000],
    [5000, 0, 1000],
    [1000, 5000, 0]
];
 
console.log(tsp(cost));

Output
3000

Time Complexity: O(n ^ 3), the time complexity of triangleInequality() function is O(n ^ 3) as we are using 3 nested loops, and all other functions are working in O(n ^ 2), and O(n ^ 2 * log n) time complexity, thus the overall time complexity will be O(n ^ 3).
Space Complexity: O(n ^ 2), to store the adjacency list, and creating MST.


Article Tags :
Practice Tags :

Similar Reads