Open In App

Check if there is a cycle with odd weight sum in an undirected graph

Improve
Improve
Like Article
Like
Save
Share
Report

Given a weighted and undirected graph, we need to find if a cycle exist in this graph such that the sum of weights of all the edges in that cycle comes out to be odd.

Examples: 

Input : Number of vertices, n = 4, 
        Number of edges, m = 4
        Weighted Edges = 
        1 2 12
        2 3 1
        4 3 1
        4 1 20
Output : No! There is no odd weight 
         cycle in the given graph

Cyclic graph

Input : Number of vertices, n = 5, 
        Number of edges, m = 3
        Weighted Edges = 
        1 2 1
        3 2 1
        3 1 1
Output : Yes! There is an odd weight 
         cycle in the given graph

The solution is based on the fact that “If a graph has no odd length cycle then it must be Bipartite, i.e., it can be colored with two colors
The idea is to convert given problem to a simpler problem where we have to just check if there is cycle of odd length or not. To convert, we do following 

  1. Convert all even weight edges into two edges of unit weight.
  2. Convert all odd weight edges to a single edge of unit weight.

Let’s make an another graph for graph shown above (in example 1)
 

cycle odd weight undirected graph

Here, edges [1 — 2] have be broken in two parts such that [1-pseudo1-2] a pseudo node has been introduced. We are doing this so that each of our even weighted edge is taken into consideration twice while the edge with odd weight is counted only once. Doing this would help us further when we color our cycle. We assign all the edges with weight 1 and then by using 2 color method traverse the whole graph.

Now we start coloring our modified graph using two colors only. In a cycle with even number of nodes, when we color it using two colors only, none of the two adjacent edges have the same color. While if we try coloring a cycle having odd number of edges, surely a situation arises where two adjacent edges have the same color. This is our pick! Thus, if we are able to color the modified graph completely using 2 colors only in a way no two adjacent edges get the same color assigned to them then there must be either no cycle in the graph or a cycle with even number of nodes. If any conflict arises while coloring a cycle with 2 colors only, then we have an odd cycle in our graph. 
Implementation: 

C++




// C++ program to check if there is a cycle of
// total odd weight
#include <bits/stdc++.h>
using namespace std;
 
// This function returns true if the current subpart
// of the forest is two colorable, else false.
bool twoColorUtil(vector<int>G[], int src, int N,
                                  int colorArr[]) {
     
    // Assign first color to source
    colorArr[src] = 1;
     
    // Create a queue (FIFO) of vertex numbers and
    // enqueue source vertex for BFS traversal
    queue <int> q;
    q.push(src);
     
    // Run while there are vertices in queue
    // (Similar to BFS)
    while (!q.empty()){
         
        int u = q.front();
        q.pop();
         
        // Find all non-colored adjacent vertices
        for (int v = 0; v < G[u].size(); ++v){
      
            // An edge from u to v exists and
            // destination v is not colored
            if (colorArr[G[u][v]] == -1){
             
                // Assign alternate color to this
                // adjacent v of u
                colorArr[G[u][v]] = 1 - colorArr[u];
                q.push(G[u][v]);
            }
 
            //  An edge from u to v exists and destination
            // v is colored with same color as u
            else if (colorArr[G[u][v]] == colorArr[u])          
                return false;
        }
    }
    return true;
}
 
// This function returns true if graph G[V][V] is two
// colorable, else false      
bool twoColor(vector<int>G[], int N){
     
     
    // Create a color array to store colors assigned
    // to all vertices. Vertex number is used as index
    // in this array. The value '-1' of  colorArr[i]
    // is used to indicate that no color is assigned
    // to vertex 'i'.  The value 1 is used to indicate
    // first color is assigned and value 0 indicates
    // second color is assigned.
    int colorArr[N];
    for (int i = 1; i <= N; ++i)
        colorArr[i] = -1;
     
    // As we are dealing with graph, the input might
    // come as a forest, thus start coloring from a
    // node and if true is returned we'll know that
    // we successfully colored the subpart of our
    // forest and we start coloring again from a new
    // uncolored node. This way we cover the entire forest.
    for (int i = 1; i <= N; i++)
        if (colorArr[i] == -1)
           if (twoColorUtil(G, i, N, colorArr) == false)
             return false;
          
        return true;
}
 
// Returns false if an odd cycle is present else true
// int info[][] is the information about our graph
// int n is the number of nodes
// int m is the number of informations given to us
bool isOddSum(int info[][3],int n,int m){
     
    // Declaring adjacency list of a graph
    // Here at max, we can encounter all the edges with
    // even weight thus there will be 1 pseudo node
    // for each edge
    vector<int> G[2*n];
     
    int pseudo = n+1;
    int pseudo_count = 0;
    for (int i=0; i<m; i++){
         
        // For odd weight edges, we directly add it
        // in our graph
        if (info[i][2]%2 == 1){
             
            int u = info[i][0];
            int v = info[i][1];
            G[u].push_back(v);
            G[v].push_back(u);
        }
 
        // For even weight edges, we break it
        else{
             
            int u = info[i][0];
            int v = info[i][1];
 
            // Entering a pseudo node between u---v
            G[u].push_back(pseudo);
            G[pseudo].push_back(u);
            G[v].push_back(pseudo);
            G[pseudo].push_back(v);
             
            // Keeping a record of number of pseudo nodes
            // inserted
            pseudo_count++;
 
            // Making a new pseudo node for next time
            pseudo++;
        }
    }
     
    // We pass number graph G[][] and total number
    // of node = actual number of nodes + number of
    // pseudo nodes added.
    return twoColor(G,n+pseudo_count);
}
 
// Driver function
int main() {
     
    // 'n' correspond to number of nodes in our
    // graph while 'm' correspond to the number 
    // of information about this graph.
    int n = 4, m = 4;
    int info[4][3] = {{1, 2, 12},
                     {2, 3, 1},
                     {4, 3, 1},
                     {4, 1, 20}};
                     
    // This function break the even weighted edges in
    // two parts. Makes the adjacency representation
    // of the graph and sends it for two coloring.
    if (isOddSum(info, n, m) == true)
        cout << "No\n";
    else
        cout << "Yes\n";
     
    return 0;
}


Java




// Java program to check if there is
// a cycle of total odd weight
import java.io.*;
import java.util.*;
 
class GFG
{
 
// This function returns true if the current subpart
// of the forest is two colorable, else false.
static boolean twoColorUtil(Vector<Integer>[] G,
                            int src, int N,
                            int[] colorArr)
{
 
    // Assign first color to source
    colorArr[src] = 1;
 
    // Create a queue (FIFO) of vertex numbers and
    // enqueue source vertex for BFS traversal
    Queue<Integer> q = new LinkedList<>();
    q.add(src);
 
    // Run while there are vertices in queue
    // (Similar to BFS)
    while (!q.isEmpty())
    {
        int u = q.peek();
        q.poll();
 
        // Find all non-colored adjacent vertices
        for (int v = 0; v < G[u].size(); ++v)
        {
 
            // An edge from u to v exists and
            // destination v is not colored
            if (colorArr[G[u].elementAt(v)] == -1)
            {
 
                // Assign alternate color to this
                // adjacent v of u
                colorArr[G[u].elementAt(v)] = 1 - colorArr[u];
                q.add(G[u].elementAt(v));
            }
 
            // An edge from u to v exists and destination
            // v is colored with same color as u
            else if (colorArr[G[u].elementAt(v)] == colorArr[u])
                return false;
        }
    }
    return true;
}
 
// This function returns true if
// graph G[V][V] is two colorable, else false
static boolean twoColor(Vector<Integer>[] G, int N)
{
 
    // Create a color array to store colors assigned
    // to all vertices. Vertex number is used as index
    // in this array. The value '-1' of colorArr[i]
    // is used to indicate that no color is assigned
    // to vertex 'i'. The value 1 is used to indicate
    // first color is assigned and value 0 indicates
    // second color is assigned.
    int[] colorArr = new int[N + 1];
    for (int i = 1; i <= N; ++i)
        colorArr[i] = -1;
 
    // As we are dealing with graph, the input might
    // come as a forest, thus start coloring from a
    // node and if true is returned we'll know that
    // we successfully colored the subpart of our
    // forest and we start coloring again from a new
    // uncolored node. This way we cover the entire forest.
    for (int i = 1; i <= N; i++)
        if (colorArr[i] == -1)
            if (twoColorUtil(G, i, N, colorArr) == false)
                return false;
 
    return true;
}
 
// Returns false if an odd cycle is present else true
// int info[][] is the information about our graph
// int n is the number of nodes
// int m is the number of informations given to us
static boolean isOddSum(int[][] info, int n, int m)
{
 
    // Declaring adjacency list of a graph
    // Here at max, we can encounter all the edges with
    // even weight thus there will be 1 pseudo node
    // for each edge
    //@SuppressWarnings("unchecked")
    Vector<Integer>[] G = new Vector[2 * n];
 
    for (int i = 0; i < 2 * n; i++)
        G[i] = new Vector<>();
 
    int pseudo = n + 1;
    int pseudo_count = 0;
    for (int i = 0; i < m; i++)
    {
 
        // For odd weight edges, we directly add it
        // in our graph
        if (info[i][2] % 2 == 1)
        {
            int u = info[i][0];
            int v = info[i][1];
            G[u].add(v);
            G[v].add(u);
        }
 
        // For even weight edges, we break it
        else
        {
            int u = info[i][0];
            int v = info[i][1];
 
            // Entering a pseudo node between u---v
            G[u].add(pseudo);
            G[pseudo].add(u);
            G[v].add(pseudo);
            G[pseudo].add(v);
 
            // Keeping a record of number of
            // pseudo nodes inserted
            pseudo_count++;
 
            // Making a new pseudo node for next time
            pseudo++;
        }
    }
 
    // We pass number graph G[][] and total number
    // of node = actual number of nodes + number of
    // pseudo nodes added.
    return twoColor(G, n + pseudo_count);
}
 
// Driver Code
public static void main(String[] args)
{
    // 'n' correspond to number of nodes in our
    // graph while 'm' correspond to the number
    // of information about this graph.
    int n = 4, m = 3;
    int[][] info = { { 1, 2, 12 }, { 2, 3, 1 },
                     { 4, 3, 1 }, { 4, 1, 20 } };
 
    // This function break the even weighted edges in
    // two parts. Makes the adjacency representation
    // of the graph and sends it for two coloring.
    if (isOddSum(info, n, m) == true)
        System.out.println("No");
    else
        System.out.println("Yes");
}
}
 
// This code is contributed by
// sanjeev2552


Python3




# Python3 program to check if there
# is a cycle of total odd weight
 
# This function returns true if the current subpart
# of the forest is two colorable, else false.
def twoColorUtil(G, src, N, colorArr): 
     
    # Assign first color to source
    colorArr[src] = 1
     
    # Create a queue (FIFO) of vertex numbers and
    # enqueue source vertex for BFS traversal
    q = [src]
     
    # Run while there are vertices in queue
    # (Similar to BFS)
    while len(q) > 0:
         
        u = q.pop(0)
         
        # Find all non-colored adjacent vertices
        for v in range(0, len(G[u])):
     
            # An edge from u to v exists and
            # destination v is not colored
            if colorArr[G[u][v]] == -1:
             
                # Assign alternate color to this
                # adjacent v of u
                colorArr[G[u][v]] = 1 - colorArr[u]
                q.append(G[u][v])
              
            # An edge from u to v exists and destination
            # v is colored with same color as u
            elif colorArr[G[u][v]] == colorArr[u]:        
                return False
         
    return True
  
# This function returns true if graph
# G[V][V] is two colorable, else false    
def twoColor(G, N):
     
    # Create a color array to store colors assigned
    # to all vertices. Vertex number is used as index
    # in this array. The value '-1' of colorArr[i]
    # is used to indicate that no color is assigned
    # to vertex 'i'. The value 1 is used to indicate
    # first color is assigned and value 0 indicates
    # second color is assigned.
    colorArr = [-1] * N
     
    # As we are dealing with graph, the input might
    # come as a forest, thus start coloring from a
    # node and if true is returned we'll know that
    # we successfully colored the subpart of our
    # forest and we start coloring again from a new
    # uncolored node. This way we cover the entire forest.
    for i in range(N):
        if colorArr[i] == -1:
            if twoColorUtil(G, i, N, colorArr) == False:
                return False
             
            return True
  
# Returns false if an odd cycle is present else true
# int info[][] is the information about our graph
# int n is the number of nodes
# int m is the number of informations given to us
def isOddSum(info, n, m):
     
    # Declaring adjacency list of a graph
    # Here at max, we can encounter all the
    # edges with even weight thus there will
    # be 1 pseudo node for each edge
    G = [[] for i in range(2*n)]
     
    pseudo, pseudo_count = n+1, 0
    for i in range(0, m):
         
        # For odd weight edges, we
        # directly add it in our graph
        if info[i][2] % 2 == 1:
             
            u, v = info[i][0], info[i][1]
            G[u].append(v)
            G[v].append(u)
          
        # For even weight edges, we break it
        else:
            u, v = info[i][0], info[i][1]
 
            # Entering a pseudo node between u---v
            G[u].append(pseudo)
            G[pseudo].append(u)
            G[v].append(pseudo)
            G[pseudo].append(v)
             
            # Keeping a record of number
            # of pseudo nodes inserted
            pseudo_count += 1
 
            # Making a new pseudo node for next time
            pseudo += 1
     
    # We pass number graph G[][] and total number
    # of node = actual number of nodes + number of
    # pseudo nodes added.
    return twoColor(G, n+pseudo_count)
  
# Driver function
if __name__ == "__main__"
     
    # 'n' correspond to number of nodes in our
    # graph while 'm' correspond to the number
    # of information about this graph.
    n, m = 4, 3
    info = [[1, 2, 12],
            [2, 3, 1],
            [4, 3, 1],
            [4, 1, 20]]
                     
    # This function break the even weighted edges in
    # two parts. Makes the adjacency representation
    # of the graph and sends it for two coloring.
    if isOddSum(info, n, m) == True:
        print("No")
    else:
        print("Yes")
     
# This code is contributed by Rituraj Jain


C#




// C# program to check if there is
// a cycle of total odd weight
using System;
using System.Collections.Generic;
 
class GFG
{
 
// This function returns true if the current subpart
// of the forest is two colorable, else false.
static bool twoColorUtil(List<int>[] G,
                        int src, int N,
                        int[] colorArr)
{
 
    // Assign first color to source
    colorArr[src] = 1;
 
    // Create a queue (FIFO) of vertex numbers and
    // enqueue source vertex for BFS traversal
    List<int> q = new List<int>();
    q.Add(src);
 
    // Run while there are vertices in queue
    // (Similar to BFS)
    while (q.Count != 0)
    {
        int u = q[0];
        q.RemoveAt(0);
 
        // Find all non-colored adjacent vertices
        for (int v = 0; v < G[u].Count; ++v)
        {
 
            // An edge from u to v exists and
            // destination v is not colored
            if (colorArr[G[u][v]] == -1)
            {
 
                // Assign alternate color to this
                // adjacent v of u
                colorArr[G[u][v]] = 1 - colorArr[u];
                q.Add(G[u][v]);
            }
 
            // An edge from u to v exists and destination
            // v is colored with same color as u
            else if (colorArr[G[u][v]] == colorArr[u])
                return false;
        }
    }
    return true;
}
 
// This function returns true if
// graph G[V,V] is two colorable, else false
static bool twoColor(List<int>[] G, int N)
{
 
    // Create a color array to store colors assigned
    // to all vertices. Vertex number is used as index
    // in this array. The value '-1' of colorArr[i]
    // is used to indicate that no color is assigned
    // to vertex 'i'. The value 1 is used to indicate
    // first color is assigned and value 0 indicates
    // second color is assigned.
    int[] colorArr = new int[N + 1];
    for (int i = 1; i <= N; ++i)
        colorArr[i] = -1;
 
    // As we are dealing with graph, the input might
    // come as a forest, thus start coloring from a
    // node and if true is returned we'll know that
    // we successfully colored the subpart of our
    // forest and we start coloring again from a new
    // uncolored node. This way we cover the entire forest.
    for (int i = 1; i <= N; i++)
        if (colorArr[i] == -1)
            if (twoColorUtil(G, i, N, colorArr) == false)
                return false;
 
    return true;
}
 
// Returns false if an odd cycle is present else true
// int info[,] is the information about our graph
// int n is the number of nodes
// int m is the number of informations given to us
static bool isOddSum(int[,] info, int n, int m)
{
 
    // Declaring adjacency list of a graph
    // Here at max, we can encounter all the edges with
    // even weight thus there will be 1 pseudo node
    // for each edge
    //@SuppressWarnings("unchecked")
    List<int>[] G = new List<int>[2 * n];
 
    for (int i = 0; i < 2 * n; i++)
        G[i] = new List<int>();
 
    int pseudo = n + 1;
    int pseudo_count = 0;
    for (int i = 0; i < m; i++)
    {
 
        // For odd weight edges, we directly add it
        // in our graph
        if (info[i, 2] % 2 == 1)
        {
            int u = info[i, 0];
            int v = info[i, 1];
            G[u].Add(v);
            G[v].Add(u);
        }
 
        // For even weight edges, we break it
        else
        {
            int u = info[i, 0];
            int v = info[i, 1];
 
            // Entering a pseudo node between u---v
            G[u].Add(pseudo);
            G[pseudo].Add(u);
            G[v].Add(pseudo);
            G[pseudo].Add(v);
 
            // Keeping a record of number of
            // pseudo nodes inserted
            pseudo_count++;
 
            // Making a new pseudo node for next time
            pseudo++;
        }
    }
 
    // We pass number graph G[,] and total number
    // of node = actual number of nodes + number of
    // pseudo nodes added.
    return twoColor(G, n + pseudo_count);
}
 
// Driver Code
public static void Main(String[] args)
{
    // 'n' correspond to number of nodes in our
    // graph while 'm' correspond to the number
    // of information about this graph.
    int n = 4, m = 3;
    int[,] info = { { 1, 2, 12 }, { 2, 3, 1 },
                    { 4, 3, 1 }, { 4, 1, 20 } };
 
    // This function break the even weighted edges in
    // two parts. Makes the adjacency representation
    // of the graph and sends it for two coloring.
    if (isOddSum(info, n, m) == true)
        Console.WriteLine("No");
    else
        Console.WriteLine("Yes");
}
}
 
// This code is contributed by PrinciRaj1992


Javascript




<script>
 
// JavaScript program to check if there is
// a cycle of total odd weight
 
 
// This function returns true if the current subpart
// of the forest is two colorable, else false.
function twoColorUtil(G, src, N, colorArr)
{
 
    // Assign first color to source
    colorArr[src] = 1;
 
    // Create a queue (FIFO) of vertex numbers and
    // enqueue source vertex for BFS traversal
    var q = [];
    q.push(src);
 
    // Run while there are vertices in queue
    // (Similar to BFS)
    while (q.length != 0)
    {
        var u = q[0];
        q.shift();
 
        // Find all non-colored adjacent vertices
        for (var v = 0; v < G[u].length; ++v)
        {
 
            // An edge from u to v exists and
            // destination v is not colored
            if (colorArr[G[u][v]] == -1)
            {
 
                // Assign alternate color to this
                // adjacent v of u
                colorArr[G[u][v]] = 1 - colorArr[u];
                q.push(G[u][v]);
            }
 
            // An edge from u to v exists and destination
            // v is colored with same color as u
            else if (colorArr[G[u][v]] == colorArr[u])
                return false;
        }
    }
    return true;
}
 
// This function returns true if
// graph G[V,V] is two colorable, else false
function twoColor(G, N)
{
 
    // Create a color array to store colors assigned
    // to all vertices. Vertex number is used as index
    // in this array. The value '-1' of colorArr[i]
    // is used to indicate that no color is assigned
    // to vertex 'i'. The value 1 is used to indicate
    // first color is assigned and value 0 indicates
    // second color is assigned.
    var colorArr =  Array(N+1).fill(-1);
 
    // As we are dealing with graph, the input might
    // come as a forest, thus start coloring from a
    // node and if true is returned we'll know that
    // we successfully colored the subpart of our
    // forest and we start coloring again from a new
    // uncolored node. This way we cover the entire forest.
    for (var i = 1; i <= N; i++)
        if (colorArr[i] == -1)
            if (twoColorUtil(G, i, N, colorArr) == false)
                return false;
 
    return true;
}
 
// Returns false if an odd cycle is present else true
// int info[,] is the information about our graph
// int n is the number of nodes
// int m is the number of informations given to us
function isOddSum(info, n, m)
{
 
    // Declaring adjacency list of a graph
    // Here at max, we can encounter all the edges with
    // even weight thus there will be 1 pseudo node
    // for each edge
    //@SuppressWarnings("unchecked")
    var G =  Array.from(Array(2*n), ()=>Array());
 
 
    var pseudo = n + 1;
    var pseudo_count = 0;
 
    for (var i = 0; i < m; i++)
    {
 
        // For odd weight edges, we directly add it
        // in our graph
        if (info[i][2] % 2 == 1)
        {
            var u = info[i][0];
            var v = info[i][1];
            G[u].push(v);
            G[v].push(u);
        }
 
        // For even weight edges, we break it
        else
        {
            var u = info[i][0];
            var v = info[i][1];
 
            // Entering a pseudo node between u---v
            G[u].push(pseudo);
            G[pseudo].push(u);
            G[v].push(pseudo);
            G[pseudo].push(v);
 
            // Keeping a record of number of
            // pseudo nodes inserted
            pseudo_count++;
 
            // Making a new pseudo node for next time
            pseudo++;
        }
    }
 
    // We pass number graph G[,] and total number
    // of node = actual number of nodes + number of
    // pseudo nodes added.
    return twoColor(G, n + pseudo_count);
}
 
// Driver Code
// 'n' correspond to number of nodes in our
// graph while 'm' correspond to the number
// of information about this graph.
var n = 4, m = 3;
var info = [ [ 1, 2, 12 ], [ 2, 3, 1 ],
                [ 4, 3, 1 ], [ 4, 1, 20 ] ];
// This function break the even weighted edges in
// two parts. Makes the adjacency representation
// of the graph and sends it for two coloring.
if (isOddSum(info, n, m) == true)
    document.write("No");
else
    document.write("Yes");
 
 
</script>


Output

No

Time Complexity: O(N*N), as we are using a loop to traverse N times and in each traversal we are calling the function twoColorUtil which costs O(N) time.
Auxiliary Space: O(N), as we are using extra space.

 



Last Updated : 19 Jul, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads