英文:
find Cliques in a graph using golang
问题
我正在尝试编写一个算法,用于在图中找到所有的团(完全子图)。每个输入顶点只能属于一个结果团。该算法的时间复杂度必须为O(N^2)
。结果中的每个团都应尽可能大。
package main
import (
"fmt"
)
type Vertex struct {
Value int
}
type CompleteSubGraph struct {
vertices []Vertex
}
func areConnected(vertex1, vertex2 Vertex) bool {
// 如果两个顶点的值之和为偶数,则它们是相连的
return (vertex1.Value+vertex2.Value)%2 == 0
}
func (vertex1 Vertex) getConnectedVertices(vertices []Vertex, maxVertices int) (verticesConnectedWithVertex1 []Vertex) {
for _, vertex2 := range vertices {
if areConnected(vertex1, vertex2) {
verticesConnectedWithVertex1 = append(verticesConnectedWithVertex1, vertex2)
}
if len(verticesConnectedWithVertex1) >= maxVertices {
break
}
}
return
}
func findAllCompleteSubGraphs(
vertices []Vertex,
maximumNumberOfVerticesForSubGraph int,
) (allCompleteSubgraphs []*CompleteSubGraph) {
/*
输入顶点中的每个顶点
只能属于一个完全子图
算法的时间复杂度不能慢于O(N^2)
其中N为vertices的长度
输入顶点中的每个顶点只能属于一个
结果完全子图
每个完全子图应尽可能大
*/
for _, vertex1 := range vertices {
connectedToVertex1 := vertex1.getConnectedVertices(vertices,
maximumNumberOfVerticesForSubGraph)
fmt.Println("顶点", vertex1)
fmt.Println("与之相连的顶点", connectedToVertex1)
}
return
}
func main() {
vertices := []Vertex{
Vertex{Value: 1}, Vertex{Value: 2}, Vertex{Value: 3},
Vertex{Value: 4}, Vertex{Value: 5}, Vertex{Value: 6},
Vertex{Value: 7}, Vertex{Value: 8}, Vertex{Value: 9},
Vertex{Value: 10}, Vertex{Value: 11}, Vertex{Value: 12},
}
fmt.Println("结果", findAllCompleteSubGraphs(vertices, 3))
}
我正在使用areConnected
函数来检查两个顶点是否通过边相连。这只是一个简单的示例,实际中可能更复杂。
我必须按照现在定义的方式使用func (vertex1 Vertex) getConnectedVertices
函数。我在下面的循环中遇到了困难:
for _, vertex1 := range vertices {
connectedToVertex1 := vertex1.getConnectedVertices(vertices,
maximumNumberOfVerticesForSubGraph)
fmt.Println("顶点", vertex1)
fmt.Println("与之相连的顶点", connectedToVertex1)
}
很难想象如何完成这个算法。我将非常感谢任何建议。
更新
我试图解决的原始问题是:根据某些特征找到彼此匹配的人群。当person1
喜欢person2
且person2
喜欢person1
时,areConnected
函数返回true
。任务是根据人员列表创建尽可能大的人群。人群越大,越好。
英文:
I am trying to write an algorithm which will find all Cliques (complete subgraphs) in a graph. Each input vertex must be only in one resulting Clique. The algorithm must have O(N^2)
time complexity. Each clique in the result must be as big as possible.
package main
import (
"fmt"
)
type Vertex struct {
Value int
}
type CompleteSubGraph struct {
vertecies []Vertex
}
func areConnected(vertex1, vertex2 Vertex) bool {
// 2 verteces are connected if their value sum is even
return (vertex1.Value+vertex2.Value)%2 == 0
}
func (vertex1 Vertex) getConnectedVertices(vertices []Vertex, maxVertices int) (verticesConnectedWithVertex1 []Vertex) {
for _, vertex2 := range vertices {
if areConnected(vertex1, vertex2) {
verticesConnectedWithVertex1 = append(verticesConnectedWithVertex1, vertex2)
}
if len(verticesConnectedWithVertex1) >= maxVertices {
break
}
}
return
}
func findAllCompleteSubGraphs(
vertices []Vertex,
maximumNumberOfVerticesForSubGraph int,
) (allCompleteSubgraphs []*CompleteSubGraph) {
/*
every vertex from input vertices
must be only in one CompleteSubGraph
the Algorithm must work not slower than O(N^2)
where N is len(vertices)
each vertex from input vertices must be only in one
resulting CompleteSubGraph
each CompleteSubGraph must be as big as possible
*/
for _, vertex1 := range vertices {
connectedToVertex1 := vertex1.getConnectedVertices(vertices,
maximumNumberOfVerticesForSubGraph)
fmt.Println("vertex", vertex1)
fmt.Println("is connected to", connectedToVertex1)
}
return
}
func main() {
vertices := []Vertex{
Vertex{Value: 1}, Vertex{Value: 2}, Vertex{Value: 3},
Vertex{Value: 4}, Vertex{Value: 5}, Vertex{Value: 6},
Vertex{Value: 7}, Vertex{Value: 8}, Vertex{Value: 9},
Vertex{Value: 10}, Vertex{Value: 11}, Vertex{Value: 12},
}
fmt.Println("result", findAllCompleteSubGraphs(vertices, 3))
}
I am checking if 2 vertecies are connected by an edge using areConnected
function. It's simple just for example but will be more complicated in real life.
I have to use func (vertex1 Vertex) getConnectedVertices
as it is defined now.
I stuck on the cycle
for _, vertex1 := range vertices {
connectedToVertex1 := vertex1.getConnectedVertices(vertices,
maximumNumberOfVerticesForSubGraph)
fmt.Println("vertex", vertex1)
fmt.Println("is connected to", connectedToVertex1)
}
Can hardly imagine how to finish the algorithm. Will appriciate any advise.
Update
The original problem which I am trying to solve:
Find groups of people who fit each other by some characteristics. AreConnected
is true when person1
likes person2
and person2
likes person1
. The task is to create groups of people with maximum size by a list of people. It is believed that big groups are better than small groups.
答案1
得分: 1
O(n^2)的时间不足以枚举图中所有可能的团,即使我们(非常乐观地)假设每个团的处理时间为O(1)。考虑一个由n/3个不相交三角形组成的n个顶点的图,即n/3个由3个顶点组成的集合,每个顶点与其所在组的其他2个顶点相连,与其他顶点不相连。注意,你可以独立地从n/3个三角形中选择一个顶点,得到一个独立集(一个由n/3个顶点组成的集合,其中任意两个顶点之间没有边相连)。现在将该图中的所有边取反:这样就得到了一个图,其中相同的顶点选择现在形成了一个大小为n/3的团。这个大小的团有3^(n/3)个,它们都是极大团(不能再添加任何顶点而保持团的性质)。3^(n/3)远远大于n^2,因此你不能希望在O(n^2)的时间内列出所有这些团。
英文:
O(n^2) isn't enough time to enumerate all possible cliques in a graph, even if we (incredibly optimistically) assume O(1) processing time per clique. Consider an n-vertex graph consisting of n/3 disjoint triangles -- that is, n/3 sets of 3 vertices, with each vertex having edges to the other 2 vertices in its group and to no other vertices. Notice that you can independently choose a single vertex from each of the n/3 triangles to get an independent set (a set of n/3 vertices, no two of which are connected by an edge). Now invert all edges in this graph: this gives a graph in which the same choice of vertices now gives a clique of size n/3. There are 3^(n/3) cliques of this size, all of which are maximal (cannot have any vertices added to them and remain cliques). 3^(n/3) is much larger than n^2, so you cannot hope to even list all these cliques in O(n^2) time.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论