граф - как найти максимальный индуцированный подграф H из G такой, что каждая вершина в H имеет степень ≥ k
вот акциз для графика.
учитывая неориентированный граф G с n вершинами и m ребрами и целое число k, дайте алгоритм O(m + n), который находит максимальный индуцированный подграф H из G такой, что каждая вершина в H имеет степень ≥ k, или докажите, что такого графа не существует. Индуцированный подграф F = (U, R) графа G = (V, E) является подмножеством U вершин V из G, а все ребра R из G такие, что обе вершины каждого ребра находятся в U.
мой первоначальная идея такова:
во-первых, этот акциз фактически спрашивает, что у нас есть все вершины S, Градусы которых больше или равны k, затем мы удаляем вершины в S, у которых нет ребра, связанного с другими. Тогда уточненный S равен H, в котором все вершины имеют степень >= k, а ребра между ними-R.
кроме того, он спрашивает O(m+n), поэтому я думаю, что мне нужно BFS или DFS. Потом я застрял.
в BFS я могу знать степень вершины. Но как только я получу степень v (вершина), я не знаю других связанных вершин, кроме его родителя. Но если у родителя нет степени >= k, я не могу исключить v, поскольку он все еще может быть связан с другими.
какие-то намеки?
Edit:
согласно ответу @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;
}
}
}
}
1 ответов
максимальный индуцированный подграф, где вершины имеют минимальную степень k называется k - core. Вы можете найти k - ядра просто многократно удаляя любые вершины со степенью меньше k.
на практике вы сначала оцениваете степени всех вершин, что равно O (m). Затем вы проходите через вершины, ища вершины со степенью меньше k. Когда вы найдете такую вершину, вырежьте ее из графика и обновить Градусы соседей, а также удаление любых соседей, чьи Градусы падают ниже k. Вам нужно посмотреть на каждую вершину хотя бы один раз (так выполнимо в O(n)) и обновить градусы не более одного раза для каждого ребра (так выполнимо в O(m)), давая общую асимптотическую оценку O(m+n).
остальные подключенные компоненты являются k-ядер. Найдите самый большой, оценив его размеры.