📌  相关文章
📜  检查无向图中是否存在权重和为奇数的环

📅  最后修改于: 2022-05-13 01:57:54.387000             🧑  作者: Mango

检查无向图中是否存在权重和为奇数的环

给定一个加权无向图,我们需要找出该图中是否存在一个循环,使得该循环中所有边的权重之和为奇数。
例子:

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

循环图

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

解决方案基于“如果一个图没有奇数长度的循环,那么它必须是二分图,即它可以用两种颜色着色”
这个想法是将给定的问题转换为一个更简单的问题,我们只需检查是否存在奇数长度的循环。要转换,我们执行以下操作

  1. 将所有偶数权边转换为单位权重的两条边。
  2. 将所有奇数权边转换为单位权重的单个边。

让我们为上面显示的图表制作另一个图表(在示例 1 中)

循环奇重无向图

这里,边 [1-2] 被分成两部分,因此 [1-pseudo1-2] 引入了一个伪节点。我们这样做是为了使我们的每个偶数加权边缘都被考虑两次,而奇数权重的边缘只计算一次。当我们为周期着色时,这样做会进一步帮助我们。我们为所有边分配权重 1,然后使用 2 色方法遍历整个图。现在我们开始仅使用两种颜色为修改后的图形着色。在具有偶数个节点的循环中,当我们仅使用两种颜色对其进行着色时,两条相邻边都没有相同的颜色。如果我们尝试为具有奇数个边的循环着色,肯定会出现两个相邻边具有相同颜色的情况。这是我们的选择!因此,如果我们能够仅使用 2 种颜色对修改后的图完全着色,并且没有两条相邻边获得相同的颜色分配给它们,那么图中一定没有循环或节点数为偶数的循环。如果在仅用 2 种颜色为循环着色时出现任何冲突,那么我们的图中就有一个奇数循环。

C++
// C++ program to check if there is a cycle of
// total odd weight
#include 
using namespace std;
 
// This function returns true if the current subpart
// of the forest is two colorable, else false.
bool twoColorUtil(vectorG[], 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  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(vectorG[], 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 G[2*n];
     
    int pseudo = n+1;
    int pseudo_count = 0;
    for (int i=0; i


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[] 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 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[] 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[] 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[] 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 q = new List();
    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[] 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[] G = new List[2 * n];
 
    for (int i = 0; i < 2 * n; i++)
        G[i] = new List();
 
    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


输出:

No