检查无向图中是否存在权重和为奇数的环
给定一个加权无向图,我们需要找出该图中是否存在一个循环,使得该循环中所有边的权重之和为奇数。
例子:
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 中)
这里,边 [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