问题描述
给定一个无向图 G = ( V , E ) G=(V,E) G=(V,E) 和一个整数 k k k,试找到 G G G 的最大规模的导出子图 H = ( U , F ) H=(U,F) H=(U,F),其中 H H H 中所有顶点的度大于或等于 k k k,或者说明不存在这样的子图。
归纳假设
假设在顶点数目小于 n n n 时,我们已知如何找到所有顶点的度大于或等于 k k k 的最大导出子图。
归纳证明
- 当 n ≤ k n{\le}k n≤k 时,则所有度均小于 k k k,不存在这样的图。当 n = k + 1 n=k+1 n=k+1 时,则可以注意到所有度大于等于 k k k 的唯一方式是一个完全图。
- 假定现在 n n n 是平凡的情况,即 n > k + 1 n>k+1 n>k+1。如果所有顶点的度大于或等于 k k k,则整个图满足要求。否则,存在一个顶点 v v v,其度小于 k k k。显然在任何 G G G 的子图中, v v v 的度都小于 k k k,因此 v v v 不在任何满足原命题的子图中。所以把 v v v 及其相连的边删除,不影响原命题。当 v v v 被删除后,图中只有 n − 1 n-1 n−1 个顶点。由归纳假设,可知如何对该问题求解。
由1,2得:对与任意无向图 G = ( V , E ) G=(V,E) G=(V,E) 和一个整数 k k k,均能完成求解任务。
算法实现
def Max_Subgraph(G, k):
""" U (G的子图, None表示无这样的子图)
Args:
G (dict): 图的邻接表 e.g. {1:[2], 2:[1]}表示节点为2的完全图
k (int): 度
"""
Du_More_Than = lambda G, n: all([len(G[v]) >= n for v in G])
Find_V = lambda G, n: [v for v in G if len(G[v]) < n]
while True:
if len(G) <= k:
return None
if len(G) == k + 1:
return G if Du_More_Than(G, k) else None
for v in Find_V(G, k):
for u in G[v]:
G[u].remove(v)
del G[v]