两个集团问题(检查图形是否可以分为两个集团)
Clique 是图的子图,使得子图中的所有顶点彼此完全连接。给定一个 Graph,判断它是否可以分成两个 Clique。
例子:
Input : G[][] = {{0, 1, 1, 0, 0},
{1, 0, 1, 1, 0},
{1, 1, 0, 0, 0},
{0, 1, 0, 0, 1},
{0, 0, 0, 1, 0}};
Output : Yes
这个问题起初看起来很棘手,但有一个简单而有趣的解决方案。如果一个图的补图是二分图,则该图可以分为两个团。所以下面是两个步骤来确定图形是否可以分成两个集团。
- 求 Graph 的补码。下面是补图,上面显示的图。作为补充,所有原始边缘都被删除。并且它们之间没有边的顶点现在有一条边连接它们。
- 如果补码是二分的,则返回 true,否则返回 false。上图是二分图。此处讨论了检查 Graph 是否为 Bipartite。
这是如何运作的?
如果补码是二分图,则图可以分为两个集合 U 和 V,使得没有边连接到同一集合的顶点。这意味着在原始图中,这些集合 U 和 V 是完全连通的。因此,原始图可以分为两个派系。
执行:
下面是上述步骤的实现。
C++
// C++ program to find out whether a given graph can be
// converted to two Cliques or not.
#include
using namespace std;
const int V = 5;
// This function returns true if subgraph reachable from
// src is Bipartite or not.
bool isBipartiteUtil(int G[][V], int src, int colorArr[])
{
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())
{
// Dequeue a vertex from queue
int u = q.front();
q.pop();
// Find all non-colored adjacent vertices
for (int v = 0; v < V; ++v)
{
// An edge from u to v exists and destination
// v is not colored
if (G[u][v] && colorArr[v] == -1)
{
// Assign alternate color to this adjacent
// v of u
colorArr[v] = 1 - colorArr[u];
q.push(v);
}
// An edge from u to v exists and destination
// v is colored with same color as u
else if (G[u][v] && colorArr[v] == colorArr[u])
return false;
}
}
// If we reach here, then all adjacent vertices can
// be colored with alternate color
return true;
}
// Returns true if a Graph G[][] is Bipartite or not. Note
// that G may not be connected.
bool isBipartite(int G[][V])
{
// 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[V];
for (int i = 0; i < V; ++i)
colorArr[i] = -1;
// One by one check all not yet colored vertices.
for (int i = 0; i < V; i++)
if (colorArr[i] == -1)
if (isBipartiteUtil(G, i, colorArr) == false)
return false;
return true;
}
// Returns true if G can be divided into
// two Cliques, else false.
bool canBeDividedinTwoCliques(int G[][V])
{
// Find complement of G[][]
// All values are complemented except
// diagonal ones
int GC[V][V];
for (int i=0; i
Java
// Java program to find out whether a given graph can be
// converted to two Cliques or not.
import java.util.ArrayDeque;
import java.util.Deque;
class GFG {
static int V = 5;
// This function returns true if subgraph reachable from
// src is Bipartite or not.
static boolean isBipartiteUtil(int G[][], int src, int colorArr[])
{
colorArr[src] = 1;
// Create a queue (FIFO) of vertex numbers and enqueue
// source vertex for BFS traversal
Deque q = new ArrayDeque<>();
q.push(src);
// Run while there are vertices in queue (Similar to BFS)
while (!q.isEmpty())
{
// Dequeue a vertex from queue
int u = q.peek();
q.pop();
// Find all non-colored adjacent vertices
for (int v = 0; v < V; ++v)
{
// An edge from u to v exists and destination
// v is not colored
if (G[u][v] == -1 && colorArr[v] == -1)
{
// Assign alternate color to this adjacent
// v of u
colorArr[v] = 1 - colorArr[u];
q.push(v);
}
// An edge from u to v exists and destination
// v is colored with same color as u
else if (G[u][v] == colorArr[u] && colorArr[v] == colorArr[u])
return false;
}
}
// If we reach here, then all adjacent vertices can
// be colored with alternate color
return true;
}
// Returns true if a Graph G[][] is Bipartite or not. Note
// that G may not be connected.
static boolean isBipartite(int G[][])
{
// 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[V];
for (int i = 0; i < V; ++i)
colorArr[i] = -1;
// One by one check all not yet colored vertices.
for (int i = 0; i < V; i++)
if (colorArr[i] == -1)
if (isBipartiteUtil(G, i, colorArr) == false)
return false;
return true;
}
// Returns true if G can be divided into
// two Cliques, else false.
static boolean canBeDividedinTwoCliques(int G[][])
{
// Find complement of G[][]
// All values are complemented except
// diagonal ones
int GC[][]=new int[V][V];
for (int i=0; i
Python3
# Python3 program to find out whether a given
# graph can be converted to two Cliques or not.
from queue import Queue
# This function returns true if subgraph
# reachable from src is Bipartite or not.
def isBipartiteUtil(G, src, colorArr):
global V
colorArr[src] = 1
# Create a queue (FIFO) of vertex numbers
# and enqueue source vertex for BFS traversal
q = Queue()
q.put(src)
# Run while there are vertices in
# queue (Similar to BFS)
while (not q.empty()):
# Dequeue a vertex from queue
u = q.get()
# Find all non-colored adjacent vertices
for v in range(V):
# An edge from u to v exists and
# destination v is not colored
if (G[u][v] and colorArr[v] == -1):
# Assign alternate color to this
# adjacent v of u
colorArr[v] = 1 - colorArr[u]
q.put(v)
# An edge from u to v exists and destination
# v is colored with same color as u
elif (G[u][v] and colorArr[v] == colorArr[u]):
return False
# If we reach here, then all adjacent
# vertices can be colored with alternate color
return True
# Returns true if a Graph G[][] is Bipartite or not.
# Note that G may not be connected.
def isBipartite(G):
global V
# 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] * V
# One by one check all not yet
# colored vertices.
for i in range(V):
if (colorArr[i] == -1):
if (isBipartiteUtil(G, i, colorArr) == False):
return False
return True
# Returns true if G can be divided into
# two Cliques, else false.
def canBeDividedinTwoCliques(G):
global V
# Find complement of G[][]
# All values are complemented
# except diagonal ones
GC = [[None] * V for i in range(V)]
for i in range(V):
for j in range(V):
GC[i][j] = not G[i][j] if i != j else 0
# Return true if complement is
# Bipartite else false.
return isBipartite(GC)
# Driver Code
V = 5
G = [[0, 1, 1, 1, 0],
[1, 0, 1, 0, 0],
[1, 1, 0, 0, 0],
[0, 1, 0, 0, 1],
[0, 0, 0, 1, 0]]
if canBeDividedinTwoCliques(G):
print("Yes")
else:
print("No")
# This code is contributed by PranchalK
输出 :
Yes
上述实现的时间复杂度为 O(V 2 )。
参考:
http://math.stackexchange.com/questions/310092/the-two-clique-problem-is-in-p-or-np-p-np-for-hypothesis