Approximate solution for Travelling Salesman Problem using MST
Last Updated :
23 Jul, 2025
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:
- Let 1 be the starting and ending point for salesman.
- Construct MST from with 1 as root using Prim's Algorithm.
- 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.
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));
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));
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.
Similar Reads
Basics & Prerequisites
Data Structures
Array Data StructureIn this article, we introduce array, implementation in different popular languages, its basic operations and commonly seen problems / interview questions. An array stores items (in case of C/C++ and Java Primitive Arrays) or their references (in case of Python, JS, Java Non-Primitive) at contiguous
3 min read
String in Data StructureA string is a sequence of characters. The following facts make string an interesting data structure.Small set of elements. Unlike normal array, strings typically have smaller set of items. For example, lowercase English alphabet has only 26 characters. ASCII has only 256 characters.Strings are immut
2 min read
Hashing in Data StructureHashing is a technique used in data structures that efficiently stores and retrieves data in a way that allows for quick access. Hashing involves mapping data to a specific index in a hash table (an array of items) using a hash function. It enables fast retrieval of information based on its key. The
2 min read
Linked List Data StructureA linked list is a fundamental data structure in computer science. It mainly allows efficient insertion and deletion operations compared to arrays. Like arrays, it is also used to implement other data structures like stack, queue and deque. Hereâs the comparison of Linked List vs Arrays Linked List:
2 min read
Stack Data StructureA Stack is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). LIFO implies that the element that is inserted last, comes out first and FILO implies that the element that is inserted first
2 min read
Queue Data StructureA Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Tree Data StructureTree Data Structure is a non-linear data structure in which a collection of elements known as nodes are connected to each other via edges such that there exists exactly one path between any two nodes. Types of TreeBinary Tree : Every node has at most two childrenTernary Tree : Every node has at most
4 min read
Graph Data StructureGraph Data Structure is a collection of nodes connected by edges. It's used to represent relationships between different entities. If you are looking for topic-wise list of problems on different topics like DFS, BFS, Topological Sort, Shortest Path, etc., please refer to Graph Algorithms. Basics of
3 min read
Trie Data StructureThe Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this
15+ min read
Algorithms
Searching AlgorithmsSearching algorithms are essential tools in computer science used to locate specific items within a collection of data. In this tutorial, we are mainly going to focus upon searching in an array. When we search an item in an array, there are two most common algorithms used based on the type of input
2 min read
Sorting AlgorithmsA Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read
Introduction to RecursionThe process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. A recursive algorithm takes one step toward solution and then recursively call itself to further move. The algorithm stops once we reach the solution
14 min read
Greedy AlgorithmsGreedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a global optimum solution. At every step of the algorithm, we make a choice that looks the best at the moment. To make the choice, we sometimes sort the array so that we can always get
3 min read
Graph AlgorithmsGraph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Dynamic Programming or DPDynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Bitwise AlgorithmsBitwise algorithms in Data Structures and Algorithms (DSA) involve manipulating individual bits of binary representations of numbers to perform operations efficiently. These algorithms utilize bitwise operators like AND, OR, XOR, NOT, Left Shift, and Right Shift.BasicsIntroduction to Bitwise Algorit
4 min read
Advanced
Segment TreeSegment Tree is a data structure that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tree
3 min read
Pattern SearchingPattern searching algorithms are essential tools in computer science and data processing. These algorithms are designed to efficiently find a particular pattern within a larger set of data. Patten SearchingImportant Pattern Searching Algorithms:Naive String Matching : A Simple Algorithm that works i
2 min read
GeometryGeometry is a branch of mathematics that studies the properties, measurements, and relationships of points, lines, angles, surfaces, and solids. From basic lines and angles to complex structures, it helps us understand the world around us.Geometry for Students and BeginnersThis section covers key br
2 min read
Interview Preparation
Practice Problem