这是图表的消费税。
给定具有n个顶点和m个边的无向图G和整数k,给出O(m + n)算法,该算法找到G的最大诱导子图H,使得H中的每个顶点具有≥k的度数,或者证明没有这样的图表存在。 图G =(V,E)的诱导子图F =(U,R)是G的顶点V的U的子集,以及G的所有边R,使得每个边的两个顶点都在U中。 / p>
我最初的想法是这样的:
首先,这个消息实际上要求我们拥有度数大于或等于k的所有顶点S,然后我们删除S中没有任何边连接到其他边的顶点。然后精化的S是H,其中所有顶点都具有度>&k,并且它们之间的边是R。
另外,它询问O(m + n),所以我认为我需要BFS或DFS。然后我卡住了。
在BFS中,我可以知道顶点的程度。但是一旦我得到v(一个顶点)的程度,我不知道除了它的父之外的其他连接顶点。但如果父母没有学位> = k,我就无法消除v,因为它可能仍与其他人联系。
任何提示?
根据@Michael J. Barber的回答,我实现了它并在这里更新代码:
任何人都可以查看代码public Graph kCore(Graph g, int k)
的关键方法吗?我做得对吗?是O(m + n)?
class EdgeNode {
EdgeNode next;
int y;
}
public class Graph {
public EdgeNode[] edges;
public int numVertices;
public boolean directed;
public Graph(int _numVertices, boolean _directed) {
numVertices = _numVertices;
directed = _directed;
edges = new EdgeNode[numVertices];
}
public void insertEdge(int x, int y) {
insertEdge(x, y, directed);
}
public void insertEdge(int x, int y, boolean _directed) {
EdgeNode edge = new EdgeNode();
edge.y = y;
edge.next = edges[x];
edges[x] = edge;
if (!_directed)
insertEdge(y, x, true);
}
public Graph kCore(Graph g, int k) {
int[] degree = new int[g.numVertices];
boolean[] deleted = new boolean[g.numVertices];
int numDeleted = 0;
updateAllDegree(g, degree);// get all degree info for every vertex
for (int i = 0;i < g.numVertices;i++) {
**if (!deleted[i] && degree[i] < k) {
deleteVertex(p.y, deleted, g);
}**
}
//Construct the kCore subgraph
Graph h = new Graph(g.numVertices - numDeleted, false);
for (int i = 0;i < g.numVertices;i++) {
if (!deleted[i]) {
EdgeNode p = g[i];
while(p!=null) {
if (!deleted[p.y])
h.insertEdge(i, p.y, true); // I just insert the good edge as directed, because i->p.y is inserted and later p.y->i will be inserted too in this loop.
p = p.next;
}
}
}
}
return h;
}
**private void deleteVertex(int i, boolean[] deleted, Graph g) {
deleted[i] = true;
EdgeNode p = g[i];
while(p!=null) {
if (!deleted[p.y] && degree[p.y] < k)
deleteVertex(p.y, deleted, g);
p = p.next;
}
}**
private void updateAllDegree(Graph g, int[] degree) {
for(int i = 0;i < g.numVertices;i++) {
EdgeNode p = g[i];
while(p!=null) {
degree[i] += 1;
p = p.next;
}
}
}
}
答案 0 :(得分:15)
顶点具有最小度 k 的最大诱导子图称为k-core。只需重复删除度数小于 k 的任何顶点,就可以找到 k -cores。
实际上,首先要评估所有顶点的度数,即O(m)。然后,您将遍历顶点,查找度小于 k 的顶点。当您找到这样的顶点时,将其从图中剪切并更新邻居的度数,同时删除其度数低于 k 的任何邻居。您需要至少查看一次每个顶点(在O(n)中可行)并且每个边最多更新一次(在O(m)中可行),给出O(m + n)的总渐近边界。
其余连接的组件是 k -cores。通过评估它们的尺寸来找到最大的一个。