Minimum Cost Edge Tour

Last Updated : 4 Oct, 2026

Given an integer n representing the number of vertices in an undirected weighted graph and an array edges[][] of size m, where edges[i] = [u, v, w] represents an edge between vertices u and v with weight w.

Find the minimum cost of a closed walk that starts and ends at the same vertex and visits every edge at least once.

Return -1 if it is not possible to visit every edge in a single closed walk.

Examples:

Input: n = 3, edges[][] = [[1, 2, 1], [2, 3, 1], [3, 1, 4]]

frame_4067

Output: 6
Explanation: The closed walk 1 -> 2 -> 3 -> 1 visits every edge exactly once. Its total cost is 1 + 1 + 4 = 6.

Input: n = 4, edges = [[1, 2, 2], [2, 3, 3], [3, 1, 1], [3, 4, 2]]

frame_4068

Output: 10
Explanation: The vertices 3 and 4 have odd degree, so the edge between them must be traversed one additional time.
The minimum total cost is 8 + 2 = 10.

Try It Yourself
redirect icon

Minimum Cost Eulerian Tour Using Floyd-Warshall with Bitmask DP

The idea is to convert the graph into a Eulerian Graph with the minimum possible extra cost.

  • Since a closed walk is a Eulerian circuit it requires every vertex to have an even degree, hence we identify the odd-degree vertices and pair them up.
  • For each pair, we repeat the shortest path between them, which makes both vertices even. Finally we take the minimum-cost way to pair all odd-degree vertices.
frame_4069

Problem arises when the graph is not eulerian, i.e. some vertices have an odd degree.

What what if the two vertices with odd degree are not neighbours?

  • We can repeat a whole path instead of a single edge.
  • Every vertex in the middle of the path gets +2 (once in, once out), so its parity is unchanged. Only the two endpoints flip.
  • So pairing two odd degree vertices (u, v) gives us extra cost = shortest distance (u, v).
  • We need shortest distances between every pair of odd degree vertices, so we precompute all-pairs shortest paths using the Floyd Warshall's Algorithm.

Now the remaining part of the problem is minimising the extra cost required to make the graph eulerian.

  • Every edge must be visited at least once, so the sum of all edge weights is always part of the cost.
  • Every vertex has even degree. For an odd-degree vertex, we need to duplicate some edges to flip its parity.
  • Duplicating a path u -> ... -> v adds 2 to every internal vertex and 1 to each endpoint. Thus, only u and v change parity.
  • Therefore, duplicating a path between two odd-degree vertices makes both even.
  • Hence, all odd-degree vertices must be paired, with each pair connected by a duplicated path. We want the pairing and paths with minimum total cost.

At this point we have 2 level of choices

  • What path to use for a pair of odd degree vertices (u, v)? The shortest path between them.
  • Which vertices do we pair together? Every pairing makes all degrees even, but they do not all cost the same, so we need the one with the smallest total.

To achieve this we use bitmask DP

  • Let k be the number of odd-degree vertices. We use a k-bit mask to represent which odd vertices have already been paired.
  • For k = 4,
    0000 means no odd degree vertices are paired,
    0011 means 1 and 2 odd degree vertices are paired,
    0101 means 1 and 3 odd degree vertices are paired.
  • Define dp[mask] as the minimum cost required to pair all odd vertices whose bits are 1. For example, dp[0101] represents the minimum cost of pairing odd degree vertices 1 and 3.
  • The same mask can be reached through different pairings. For example, 1111 can be reached by pairing (1,2) and (3,4), or by pairing (1,3) and (2,4). This creates overlapping sub-problems.
  • From a given mask, find the first unpaired odd vertex i, i.e. the first bit that is 0.
  • Pair i with every other unpaired vertex j and mark both as paired. The new state is newMask = mask | (1 << i) | (1 << j), with an additional cost of dist[odd[i]][odd[j]].
  • Take the minimum cost among all possible choices of j. This explores every possible pairing while storing only the cheapest cost for each state.

Finally:

  • Build the adjacency information, the degree array, and totalCost.
  • Check that all vertices with edges are connected (BFS). If not, return -1.
  • Run Floyd-Warshall to get shortest distances between all pairs.
  • Collect the odd-degree vertices. If there are none, return totalCost.
  • Run the bitmask DP over the odd vertices.
  • Return totalCost + dp[(1 << k) - 1].

Consider the following example: n = 5, edges = [[1,2,2], [2,3,1], [3,4,1], [4,5,2], [2,4,1]]

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

int pairCost(int mask, vector<int> &odd, vector<vector<int>> &dist, vector<int> &dp)
{
    int k = odd.size();

    if (mask == (1 << k) - 1)
        return 0;

    if (dp[mask] != -1)
        return dp[mask];

    int first = 0;

    while (mask & (1 << first))
        first++;

    int ans = INT_MAX;

    // Pair the first unpaired odd-degree vertex with every other unpaired vertex.

    for (int j = first + 1; j < k; j++)
    {
        if (!(mask & (1 << j)))
        {
            int newMask = mask | (1 << first) | (1 << j);

            int cost = dist[odd[first]][odd[j]] + pairCost(newMask, odd, dist, dp);

            ans = min(ans, cost);
        }
    }

    return dp[mask] = ans;
}

int minTourCost(int n, vector<vector<int>> &edges)
{
    const int INF = 1e9;

    vector<vector<int>> dist(n, vector<int>(n, INF));
    vector<vector<int>> adj(n);
    vector<int> degree(n, 0);

    int totalCost = 0;

    // Initialize distance from every vertex to itself as zero.

    for (int i = 0; i < n; i++)
        dist[i][i] = 0;

    // Build the graph, calculate degrees, and store the total edge cost.

    for (auto &edge : edges)
    {
        int u = edge[0] - 1;
        int v = edge[1] - 1;
        int w = edge[2];

        dist[u][v] = min(dist[u][v], w);
        dist[v][u] = min(dist[v][u], w);

        adj[u].push_back(v);
        adj[v].push_back(u);

        degree[u]++;
        degree[v]++;

        totalCost += w;
    }

    // Find a vertex that is incident to at least one edge.

    int start = -1;

    for (int i = 0; i < n; i++)
    {
        if (degree[i] > 0)
        {
            start = i;
            break;
        }
    }

    if (start == -1)
        return 0;

    // Check that all vertices with edges belong to the same component.

    vector<bool> visited(n, false);
    queue<int> q;

    q.push(start);
    visited[start] = true;

    while (!q.empty())
    {
        int u = q.front();
        q.pop();

        for (int v : adj[u])
        {
            if (!visited[v])
            {
                visited[v] = true;
                q.push(v);
            }
        }
    }

    for (int i = 0; i < n; i++)
    {
        if (degree[i] > 0 && !visited[i])
            return -1;
    }

    // Compute the shortest distance between every pair of vertices.

    for (int k = 0; k < n; k++)
    {
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (dist[i][k] < INF && dist[k][j] < INF)
                {
                    dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
                }
            }
        }
    }

    vector<int> odd;

    // Collect all vertices having odd degree.

    for (int i = 0; i < n; i++)
    {
        if (degree[i] % 2 == 1)
            odd.push_back(i);
    }

    int k = odd.size();

    if (k == 0)
        return totalCost;

    vector<int> dp(1 << k, -1);

    // Find the minimum additional cost required to pair all odd vertices.

    int extraCost = pairCost(0, odd, dist, dp);

    return totalCost + extraCost;
}

int main()
{
    int n = 4;

    vector<vector<int>> edges = {{1, 2, 2}, {2, 3, 3}, {3, 1, 1}, {3, 4, 2}};

    cout << minTourCost(n, edges) << '\n';

    return 0;
}
Java
import java.util.*;

class GFG {

    static int pairCost(int mask, int[] odd, int[][] dist,
                        int[] dp)
    {
        int k = odd.length;

        if (mask == (1 << k) - 1)
            return 0;

        if (dp[mask] != -1)
            return dp[mask];

        int first = 0;

        while ((mask & (1 << first)) != 0)
            first++;

        int ans = Integer.MAX_VALUE;

        // Pair the first unpaired odd-degree vertex with
        // every other unpaired vertex.

        for (int j = first + 1; j < k; j++) {
            if ((mask & (1 << j)) == 0) {
                int newMask
                    = mask | (1 << first) | (1 << j);

                int cost
                    = dist[odd[first]][odd[j]]
                      + pairCost(newMask, odd, dist, dp);

                ans = Math.min(ans, cost);
            }
        }

        return dp[mask] = ans;
    }

    static int minTourCost(int n, int[][] edges)
    {
        final int INF = 1000000000;

        int[][] dist = new int[n][n];
        int[] degree = new int[n];
        ArrayList<Integer>[] adj = new ArrayList[n];

        for (int i = 0; i < n; i++) {
            Arrays.fill(dist[i], INF);
            dist[i][i] = 0;
            adj[i] = new ArrayList<>();
        }

        int totalCost = 0;

        // Build the graph, calculate degrees, and store the
        // total edge cost.

        for (int[] edge : edges) {
            int u = edge[0] - 1;
            int v = edge[1] - 1;
            int w = edge[2];

            dist[u][v] = Math.min(dist[u][v], w);
            dist[v][u] = Math.min(dist[v][u], w);

            adj[u].add(v);
            adj[v].add(u);

            degree[u]++;
            degree[v]++;

            totalCost += w;
        }

        // Find a vertex that is incident to at least one
        // edge.

        int start = -1;

        for (int i = 0; i < n; i++) {
            if (degree[i] > 0) {
                start = i;
                break;
            }
        }

        if (start == -1)
            return 0;

        // Check that all vertices with edges belong to the
        // same component.

        boolean[] visited = new boolean[n];
        Queue<Integer> q = new LinkedList<>();

        q.add(start);
        visited[start] = true;

        while (!q.isEmpty()) {
            int u = q.poll();

            for (int v : adj[u]) {
                if (!visited[v]) {
                    visited[v] = true;
                    q.add(v);
                }
            }
        }

        for (int i = 0; i < n; i++) {
            if (degree[i] > 0 && !visited[i])
                return -1;
        }

        // Compute the shortest distance between every pair
        // of vertices.

        for (int k = 0; k < n; k++) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    if (dist[i][k] < INF
                        && dist[k][j] < INF) {
                        dist[i][j] = Math.min(
                            dist[i][j],
                            dist[i][k] + dist[k][j]);
                    }
                }
            }
        }

        ArrayList<Integer> oddList = new ArrayList<>();

        // Collect all vertices having odd degree.

        for (int i = 0; i < n; i++) {
            if (degree[i] % 2 == 1)
                oddList.add(i);
        }

        int k = oddList.size();
        int[] odd = new int[k];

        for (int i = 0; i < k; i++)
            odd[i] = oddList.get(i);

        if (k == 0)
            return totalCost;

        int[] dp = new int[1 << k];
        Arrays.fill(dp, -1);

        // Find the minimum additional cost required to pair
        // all odd vertices.

        int extraCost = pairCost(0, odd, dist, dp);

        return totalCost + extraCost;
    }

    public static void main(String[] args)
    {
        int n = 4;

        int[][] edges = { { 1, 2, 2 },
                          { 2, 3, 3 },
                          { 3, 1, 1 },
                          { 3, 4, 2 } };

        System.out.println(minTourCost(n, edges));
    }
}
Python
from collections import deque


def pairCost(mask, odd, dist, dp):
    k = len(odd)

    if mask == (1 << k) - 1:
        return 0

    if dp[mask] != -1:
        return dp[mask]

    first = 0

    while mask & (1 << first):
        first += 1

    ans = float('inf')

    # Pair the first unpaired odd-degree vertex with every other unpaired vertex.

    for j in range(first + 1, k):
        if not (mask & (1 << j)):
            newMask = mask | (1 << first) | (1 << j)

            cost = dist[odd[first]][odd[j]] + pairCost(
                newMask, odd, dist, dp
            )

            ans = min(ans, cost)

    dp[mask] = ans
    return ans


def minTourCost(n, edges):
    INF = 10**9

    dist = [[INF] * n for _ in range(n)]
    degree = [0] * n
    adj = [[] for _ in range(n)]

    totalCost = 0

    # Initialize distance from every vertex to itself as zero.

    for i in range(n):
        dist[i][i] = 0

    # Build the graph, calculate degrees, and store the total edge cost.

    for edge in edges:
        u = edge[0] - 1
        v = edge[1] - 1
        w = edge[2]

        dist[u][v] = min(dist[u][v], w)
        dist[v][u] = min(dist[v][u], w)

        adj[u].append(v)
        adj[v].append(u)

        degree[u] += 1
        degree[v] += 1

        totalCost += w

    # Find a vertex that is incident to at least one edge.

    start = -1

    for i in range(n):
        if degree[i] > 0:
            start = i
            break

    if start == -1:
        return 0

    # Check that all vertices with edges belong to the same component.

    visited = [False] * n
    q = deque([start])
    visited[start] = True

    while q:
        u = q.popleft()

        for v in adj[u]:
            if not visited[v]:
                visited[v] = True
                q.append(v)

    for i in range(n):
        if degree[i] > 0 and not visited[i]:
            return -1

    # Compute the shortest distance between every pair of vertices.

    for k in range(n):
        for i in range(n):
            for j in range(n):
                if dist[i][k] < INF and dist[k][j] < INF:
                    dist[i][j] = min(
                        dist[i][j],
                        dist[i][k] + dist[k][j]
                    )

    odd = []

    # Collect all vertices having odd degree.

    for i in range(n):
        if degree[i] % 2 == 1:
            odd.append(i)

    k = len(odd)

    if k == 0:
        return totalCost

    dp = [-1] * (1 << k)

    # Find the minimum additional cost required to pair all odd vertices.

    extraCost = pairCost(0, odd, dist, dp)

    return totalCost + extraCost


if __name__ == "__main__":
    n = 4

    edges = [
        [1, 2, 2],
        [2, 3, 3],
        [3, 1, 1],
        [3, 4, 2]
    ]

    print(minTourCost(n, edges))
C#
using System;
using System.Collections.Generic;

class GFG {
    static int pairCost(int mask, int[] odd, int[][] dist,
                        int[] dp)
    {
        int k = odd.Length;

        if (mask == (1 << k) - 1)
            return 0;

        if (dp[mask] != -1)
            return dp[mask];

        int first = 0;

        while ((mask & (1 << first)) != 0)
            first++;

        int ans = int.MaxValue;

        // Pair the first unpaired odd-degree vertex with
        // every other unpaired vertex.

        for (int j = first + 1; j < k; j++) {
            if ((mask & (1 << j)) == 0) {
                int newMask
                    = mask | (1 << first) | (1 << j);

                int cost
                    = dist[odd[first]][odd[j]]
                      + pairCost(newMask, odd, dist, dp);

                ans = Math.Min(ans, cost);
            }
        }

        return dp[mask] = ans;
    }

    static int minTourCost(int n, int[][] edges)
    {
        const int INF = 1000000000;

        int[][] dist = new int[n][];
        int[] degree = new int[n];
        List<int>[] adj = new List<int>[ n ];

        for (int i = 0; i < n; i++) {
            dist[i] = new int[n];
            Array.Fill(dist[i], INF);

            dist[i][i] = 0;
            adj[i] = new List<int>();
        }

        int totalCost = 0;

        // Build the graph, calculate degrees, and store the
        // total edge cost.

        foreach(int[] edge in edges)
        {
            int u = edge[0] - 1;
            int v = edge[1] - 1;
            int w = edge[2];

            dist[u][v] = Math.Min(dist[u][v], w);
            dist[v][u] = Math.Min(dist[v][u], w);

            adj[u].Add(v);
            adj[v].Add(u);

            degree[u]++;
            degree[v]++;

            totalCost += w;
        }

        // Find a vertex that is incident to at least one
        // edge.

        int start = -1;

        for (int i = 0; i < n; i++) {
            if (degree[i] > 0) {
                start = i;
                break;
            }
        }

        if (start == -1)
            return 0;

        // Check that all vertices with edges belong to the
        // same component.

        bool[] visited = new bool[n];
        Queue<int> q = new Queue<int>();

        q.Enqueue(start);
        visited[start] = true;

        while (q.Count > 0) {
            int u = q.Dequeue();

            foreach(int v in adj[u])
            {
                if (!visited[v]) {
                    visited[v] = true;
                    q.Enqueue(v);
                }
            }
        }

        for (int i = 0; i < n; i++) {
            if (degree[i] > 0 && !visited[i])
                return -1;
        }

        // Compute the shortest distance between every pair
        // of vertices.

        for (int mid = 0; mid < n; mid++) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    if (dist[i][mid] < INF
                        && dist[mid][j] < INF) {
                        dist[i][j] = Math.Min(
                            dist[i][j],
                            dist[i][mid] + dist[mid][j]);
                    }
                }
            }
        }

        List<int> oddList = new List<int>();

        // Collect all vertices having odd degree.

        for (int i = 0; i < n; i++) {
            if (degree[i] % 2 == 1)
                oddList.Add(i);
        }

        int k = oddList.Count;
        int[] odd = new int[k];

        for (int i = 0; i < k; i++)
            odd[i] = oddList[i];

        if (k == 0)
            return totalCost;

        int[] dp = new int[1 << k];

        Array.Fill(dp, -1);

        // Find the minimum additional cost required to pair
        // all odd vertices.

        int extraCost = pairCost(0, odd, dist, dp);

        return totalCost + extraCost;
    }

    public static void Main()
    {
        int n = 4;

        int[][] edges = { new int[] { 1, 2, 2 },
                          new int[] { 2, 3, 3 },
                          new int[] { 3, 1, 1 },
                          new int[] { 3, 4, 2 } };

        Console.WriteLine(minTourCost(n, edges));
    }
}
JavaScript
function pairCost(mask, odd, dist, dp)
{
    const k = odd.length;

    if (mask === (1 << k) - 1)
        return 0;

    if (dp[mask] !== -1)
        return dp[mask];

    let first = 0;

    while (mask & (1 << first))
        first++;

    let ans = Infinity;

    // Pair the first unpaired odd-degree vertex with every
    // other unpaired vertex.

    for (let j = first + 1; j < k; j++) {
        if (!(mask & (1 << j))) {
            const newMask = mask | (1 << first) | (1 << j);

            const cost = dist[odd[first]][odd[j]]
                         + pairCost(newMask, odd, dist, dp);

            ans = Math.min(ans, cost);
        }
    }

    dp[mask] = ans;
    return ans;
}

function minTourCost(n, edges)
{
    const INF = 1e9;

    const dist = Array.from({length : n},
                            () => Array(n).fill(INF));

    const degree = Array(n).fill(0);
    const adj = Array.from({length : n}, () => []);

    let totalCost = 0;

    // Initialize distance from every vertex to itself as
    // zero.

    for (let i = 0; i < n; i++)
        dist[i][i] = 0;

    // Build the graph, calculate degrees, and store the
    // total edge cost.

    for (const edge of edges) {
        const u = edge[0] - 1;
        const v = edge[1] - 1;
        const w = edge[2];

        dist[u][v] = Math.min(dist[u][v], w);
        dist[v][u] = Math.min(dist[v][u], w);

        adj[u].push(v);
        adj[v].push(u);

        degree[u]++;
        degree[v]++;

        totalCost += w;
    }

    // Find a vertex that is incident to at least one edge.

    let start = -1;

    for (let i = 0; i < n; i++) {
        if (degree[i] > 0) {
            start = i;
            break;
        }
    }

    if (start === -1)
        return 0;

    // Check that all vertices with edges belong to the same
    // component.

    const visited = Array(n).fill(false);
    const queue = [ start ];

    visited[start] = true;

    let front = 0;

    while (front < queue.length) {
        const u = queue[front++];

        for (const v of adj[u]) {
            if (!visited[v]) {
                visited[v] = true;
                queue.push(v);
            }
        }
    }

    for (let i = 0; i < n; i++) {
        if (degree[i] > 0 && !visited[i])
            return -1;
    }

    // Compute the shortest distance between every pair of
    // vertices.

    for (let k = 0; k < n; k++) {
        for (let i = 0; i < n; i++) {
            for (let j = 0; j < n; j++) {
                if (dist[i][k] < INF && dist[k][j] < INF) {
                    dist[i][j]
                        = Math.min(dist[i][j],
                                   dist[i][k] + dist[k][j]);
                }
            }
        }
    }

    const odd = [];

    // Collect all vertices having odd degree.

    for (let i = 0; i < n; i++) {
        if (degree[i] % 2 === 1)
            odd.push(i);
    }

    const k = odd.length;

    if (k === 0)
        return totalCost;

    const dp = Array(1 << k).fill(-1);

    // Find the minimum additional cost required to pair all
    // odd vertices.

    const extraCost = pairCost(0, odd, dist, dp);

    return totalCost + extraCost;
}

// Driver Code
const n = 4;

const edges =
    [ [ 1, 2, 2 ], [ 2, 3, 3 ], [ 3, 1, 1 ], [ 3, 4, 2 ] ];

console.log(minTourCost(n, edges));

Output
10

Time Complexity: O(n^3 + 2^k * k^2)

  • Floyd-Warshall takes O(n^3).
  • Bitmask DP has 2^k states where k is the number of vertices with odd degree, and each state can try up to O(k^2) pairings.

Space Complexity: O(n^2 + 2^k)

  • O(n^2) for the distance matrix.
  • O(2^k) for the DP array.
Comment