Find the minimum spanning tree with alternating colored edges

Given a graph with N nodes and M edges where each edge has a color (either black or green) and a cost associated with it. Find the minimum spanning tree of the graph such that every path in the tree is made up of alternating colored edges. Examples:
Input: N = 3, M = 4
Output: 6 Input: N = 4, M = 6
Output: 4
Approach:Â
- The first observation we make here is every such kind of spanning tree will be a chain. To prove it, suppose we have a tree that is not a chain and every path in it is made up of alternating edges. Then we can deduce that at least 1 node has a degree of 3. Out of these 3 edges, at least 2 will have the same color. The path using these 2 edges will never follow the conditions and Hence, such kind of tree is always a chain.
- Now we can find a chain with minimum cost and alternating edges using bitmask-dp, dp[mask(2^n)][Node(n)][col_of_last_edge(2)] where the mask is the bitmask of nodes we’ve added to the chain. Node is the last node we added to the chain.col_of_last_edge is the color of edge use to connect Node.
- To transition from 1 state to another state we visit the adjacency list of the last node and use those edges which have color != col_of_last_edge.
Below is the implementation of the above approach:Â
C++
// C++ program for the// above approach#include <bits/stdc++.h>using namespace std;Â
int graph[18][18][2];Â
// Initializing dp of size =// (2^18)*18*2.long long dp[1 << 18][18][2];Â
// Recursive Function to calculate// Minimum Cost with alternate // colour edgeslong long minCost(int n, int m, int mask, int prev, int col){    // Base case    if (mask == ((1 << n) - 1)) {        return 0;    }    // If already calculated    if (dp[mask][prev][col == 1] != 0) {        return dp[mask][prev][col == 1];    }Â
    long long ans = 1e9;Â
    for (int i = 0; i < n; i++) {        for (int j = 0; j < 2; j++) {            // Masking previous edges            // as explained in above formula.            if (graph[prev][i][j] && !(mask & (1 << i))                 && (j != col)) {                long long z = graph[prev][i][j] +                               minCost(n,m,mask|(1<<i),i,j);                ans = min(z, ans);            }        }    }Â
    return dp[mask][prev][col == 1] = ans;}Â
// Function to Adjacency// List Representation // of a Graphvoid makeGraph(vector<pair<pair<int,int>,                      pair<int,char>>>& vp,int m){Â
  for (int i = 0; i < m; i++) {    int a = vp[i].first.first - 1;    int b = vp[i].first.second - 1;    int cost = vp[i].second.first;    char color = vp[i].second.second;    graph[a][b][color == 'W'] = cost;    graph[b][a][color == 'W'] = cost;  }}Â
// Function to getCost// for the Minimum Spanning// Tree Formedint getCost(int n,int m){         // Assigning maximum    // possible value.    long long ans = 1e9;Â
    for (int i = 0; i < n; i++) {        ans = min(ans, minCost(n, m, 1 << i, i, 2));    }Â
    if (ans != 1e9) {        return ans;    }    else {        return -1;    }}Â
// Driver codeint main(){    int n = 3, m = 4;    vector<pair<pair<int, int>, pair<int, char> > > vp = {        { { 1, 2 }, { 2, 'B' } },        { { 1, 2 }, { 3, 'W' } },        { { 2, 3 }, { 4, 'W' } },        { { 2, 3 }, { 5, 'B' } }    };Â
    makeGraph(vp,m);    cout << getCost(n,m) << '\n';         return 0;} |
Python3
# Python implementation of the approachÂ
graph = [[[0, 0] for i in range(18)] for j in range(18)]Â
# Initializing dp of size =# (2^18)*18*2.dp = [[[0, 0] for i in range(18)] for j in range(1 << 15)]Â
# Recursive Function to calculate# Minimum Cost with alternate# colour edgesdef minCost(n: int, m: int, mask: Â Â Â Â Â Â Â Â Â Â Â Â int, prev: int, col: int) -> int:Â Â Â Â global dpÂ
    # Base case    if mask == ((1 << n) - 1):        return 0Â
    # If already calculated    if dp[mask][prev][col == 1] != 0:        return dp[mask][prev][col == 1]Â
    ans = int(1e9)Â
    for i in range(n):        for j in range(2):Â
            # Masking previous edges            # as explained in above formula.            if graph[prev][i][j] and not (mask & (1 << i)) \                and (j != col):                z = graph[prev][i][j] + minCost(n,                        m, mask | (1 << i), i, j)                ans = min(z, ans)Â
    dp[mask][prev][col == 1] = ans    return dp[mask][prev][col == 1]Â
# Function to Adjacency# List Representation# of a Graphdef makeGraph(vp: list, m: int):    global graph    for i in range(m):        a = vp[i][0][0] - 1        b = vp[i][0][1] - 1        cost = vp[i][1][0]        color = vp[i][1][1]        graph[a][b][color == 'W'] = cost        graph[b][a][color == 'W'] = costÂ
# Function to getCost# for the Minimum Spanning# Tree Formeddef getCost(n: int, m: int) -> int:Â
    # Assigning maximum    # possible value.    ans = int(1e9)    for i in range(n):        ans = min(ans, minCost(n, m, 1 << i, i, 2))Â
    if ans != int(1e9):        return ans    else:        return -1Â
# Driver Codeif __name__ == "__main__":Â
    n = 3    m = 4    vp = [[[1, 2], [2, 'B']],        [[1, 2], [3, 'W']],        [[2, 3], [4, 'W']],        [[2, 3], [5, 'B']]]    makeGraph(vp, m)    print(getCost(n, m))Â
# This code is contributed by# sanjeev2552 |
C#
// C# program for the// above approachÂ
using System;using System.Collections.Generic;Â
class Program{   // Initializing dp of size =// (2^18)*18*2.    static int[,,] graph = new int[18, 18, 2];    static long[,,] dp = new long[1 << 18, 18, 2];// Recursive Function to calculate// Minimum Cost with alternate // colour edges    static long minCost(int n, int m, int mask, int prev, int col)    {        if (mask == ((1 << n) - 1))        {            return 0;        }                 if(col!=1)col=0;         // If already calculated        if (dp[mask, prev, col] != 0)        {            return dp[mask, prev, col];        }Â
        long ans = 1000000000;Â
        for (int i = 0; i < n; i++)        {            for (int j = 0; j < 2; j++)            {                if (graph[prev, i, j] != 0 && (mask & (1 << i)) == 0                    && (j != col))                {                    long z = graph[prev, i, j] + minCost(n, m, mask | (1 << i), i, j);                    ans = Math.Min(z, ans);                }            }        }Â
        return dp[mask, prev, col] = ans;    }Â
// Function to Adjacency// List Representation // of a Graph    static void MakeGraph(List<Tuple<Tuple<int, int>, Tuple<int, char>>> vp, int m)    {        for (int i = 0; i < m; i++)        {            int a = vp[i].Item1.Item1 - 1;            int b = vp[i].Item1.Item2 - 1;            int cost = vp[i].Item2.Item1;            char color = vp[i].Item2.Item2;            graph[a, b, color == 'W' ? 1 : 0] = cost;            graph[b, a, color == 'W' ? 1 : 0] = cost;        }    }// Function to getCost// for the Minimum Spanning// Tree Formed    static int GetCost(int n, int m)    {        long ans = 1000000000;Â
        for (int i = 0; i < n; i++)        {            ans = Math.Min(ans, minCost(n, m, 1 << i, i, 2));        }Â
        if (ans != 1000000000)        {            return (int)ans;        }        else        {            return -1;        }    }  // Driver code     static void Main(string[] args)        {            int n = 3, m = 4;            List<Tuple<Tuple<int, int>, Tuple<int, char>>> vp = new List<Tuple<Tuple<int, int>, Tuple<int, char>>>()            {                Tuple.Create(Tuple.Create(1, 2), Tuple.Create(2, 'B')),                Tuple.Create(Tuple.Create(1, 2), Tuple.Create(3, 'W')),                Tuple.Create(Tuple.Create(2, 3), Tuple.Create(4, 'W')),                Tuple.Create(Tuple.Create(2, 3), Tuple.Create(5, 'B'))            };Â
            MakeGraph(vp, m);            Console.WriteLine(GetCost(n, m));        }} |
Javascript
//JavaScript program for the// above approachÂ
// Initializing dp of size =// (2^18)*18*2.let graph = new Array(18).fill().map(() =>Â Â new Array(18).fill().map(() => new Array(2).fill(0)));let dp = new Array(1 << 18).fill().map(() =>Â Â new Array(18).fill().map(() => new Array(2).fill(0)));Â
// Recursive Function to calculate// Minimum Cost with alternate// colour edgesfunction minCost(n, m, mask, prev, col) {Â Â if (mask == (1 << n) - 1) {Â Â Â Â return 0;Â Â }Â
  if (col != 1) col = 0;  // If already calculated  if (dp[mask][prev][col] != 0) {    return dp[mask][prev][col];  }Â
  let ans = 1000000000;Â
  for (let i = 0; i < n; i++) {    for (let j = 0; j < 2; j++) {      if (        graph[prev][i][j] != 0 &&        (mask & (1 << i)) == 0 &&        j != col      ) {        let z = graph[prev][i][j] + minCost(n, m, mask | (1 << i), i, j);        ans = Math.min(z, ans);      }    }  }Â
  return (dp[mask][prev][col] = ans);}Â
// Function to Adjacency// List Representation// of a Graphfunction makeGraph(vp, m) {Â Â for (let i = 0; i < m; i++) {Â Â Â Â let a = vp[i][0][0] - 1;Â Â Â Â let b = vp[i][0][1] - 1;Â Â Â Â let cost = vp[i][1][0];Â Â Â Â let color = vp[i][1][1];Â Â Â Â graph[a][b][color == 'W' ? 1 : 0] = cost;Â Â Â Â graph[b][a][color == 'W' ? 1 : 0] = cost;Â Â }}Â
// Function to getCost// for the Minimum Spanning// Tree Formedfunction getCost(n, m) {  // Assigning maximum  // possible value.  let ans = 1000000000;Â
  for (let i = 0; i < n; i++) {    ans = Math.min(ans, minCost(n, m, 1 << i, i, 2));  }Â
  if (ans != 1000000000) {    return ans;  } else {    return -1;  }}Â
// Driver codelet n = 3,  m = 4;let vp = [  [[1, 2], [2, 'B']],  [[1, 2], [3, 'W']],  [[2, 3], [4, 'W']],  [[2, 3], [5, 'B']]];Â
makeGraph(vp, m);console.log(getCost(n, m));Â
// This code is contributed by rutikbhosale |
Output:
6
Time Complexity: O(2^N * (M + N))
Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!
Output: 6 Input: N = 4, M = 6 


