连通子图与连通子图直径的求解-python实现

背景描述

连通子图

提供一个文本,文本中每行记录了两个字母,代表一个连接。这个文本记录了一个无向图。
举例:
A,B
代表A,B之间有连接。
每一个有连接点的子集组成了一个连通子图。
比如下面这个文本中:
A,B
B,C
C,A
D,E
C,F
F,G
有两个连通子图[‘A’, ‘B’, ‘C’, ‘F’, ‘G’] 和 [‘D’, ‘E’]

连通子图直径

连通子图中任意两点均有路径相连。
定义:任意两点间的距离为所有连接中的最短路径长度
定义:连通子图的直径为连通子图中所有距离中的最大值

问题

1.给定一文本,求其对应的所有连通子图

2.求该文本中所有连通子图的直径

解决方案

说明:环境 python3

#encoding:UTF-8
map=['A,B', 'B,C', 'C,A', 'D,E', 'C,F', 'F,G']
def Generate_map_dic(map):
    '''
    构造邻接矩阵行列编号与图中节点的映射关系
    按节点在原文本中出现顺序排序
    '''
    link_2_num={}
    all_point=[]
    if not map:
        return False
    flag=0
    for con in map:
        cur = con.split(',')
        if cur[0] not in all_point :
            link_2_num[cur[0]]=flag
            all_point.append(cur[0])
            flag +=1
        if cur[1] not in all_point :
            link_2_num[cur[1]]=flag
            all_point.append(cur[1])
            flag +=1
    return link_2_num
link_2_num = Generate_map_dic(map)
print ('link_2_num',link_2_num)
def Generate_con_mat(map,link_2_num):
    '''
    构造邻接矩阵
    '''
    con_mat=[[0 for i in range(0,len(link_2_num))] for j in range(0,len(link_2_num))]
    for con in map :
        cur = con.split(',')
        con_mat[link_2_num[cur[0]]][link_2_num[cur[1]]] = 1
        con_mat[link_2_num[cur[1]]][link_2_num[cur[0]]] = 1
    return con_mat
con_mat = Generate_con_mat(map,link_2_num)
print ('con_mat',con_mat)
def Get_sub_maps(con_mat,link_2_num):
    '''
    计算所有连通子图
    '''
    if not con_mat or len(con_mat)<2:
        return False
    sub_map = []
    nodes = []
    for i in range(len(con_mat)):
        tmp_map = []
        if i not in nodes:
            nodes.append(i)
            tmp_map.append(i)
            to_search = [i]
            while to_search:
                flag=to_search.pop()
                for j in range(len(con_mat[flag])):
                    if con_mat[flag][j]==1 and j not in nodes:
                        to_search.append(j)
                        nodes.append(j)
                        tmp_map.append(j)
            sub_map.append(tmp_map)
    #以下将数字表示映射回字母
    new_dict = {v : k for k, v in link_2_num.items()}
    new_sub_map = []
    for map in sub_map:
        sub = []
        for item in map:
            sub.append(new_dict[item])
        new_sub_map.append(sub)
    return new_sub_map
sub_map = Get_sub_maps(con_mat,link_2_num)
print (sub_map) 

def Count_dis(con_mat,p1,p2):
    '''
    计算邻接矩阵中任意两点的距离
    返回-1代表两点间无通路连接
    采用广度优先搜索(BFS)
    '''
    to_search=[p1]
    finish_search=[]
    dis = 0
    flag=-1
    while to_search :
        tmp=[]
        for point in to_search :
            finish_search.append(point)
            cur = con_mat[point]
            for i in range(len(cur)):
                if cur[i]==1 :
                    if i == p2 :
                        dis += 1
                        return dis
                    if i not in finish_search and i not in to_search :
                        tmp.append(i)
        dis += 1
        to_search = tmp
    return flag
print ('distance of these two points is',Count_dis(con_mat,0,5))

def Count_d_of_sub_map(link_2_num,con_mat,sub_map):
    '''
    计算连接子图的直径
    '''
    d = -1
    for i in range(len(sub_map)):
        for j in range(i+1,len(sub_map)):
            d = max(d,Count_dis(con_mat,link_2_num[sub_map[i]],link_2_num[sub_map[j]]))
    return d
print ('diameter of sub_map',sub_map[0],'is',Count_d_of_sub_map(link_2_num,con_mat,sub_map[0]))
print ('diameter of sub_map',sub_map[1],'is',Count_d_of_sub_map(link_2_num,con_mat,sub_map[1]))

代码输出

link_2_num {'G': 6, 'D': 3, 'C': 2, 'B': 1, 'F': 5, 'A': 0, 'E': 4}
con_mat [[0, 1, 1, 0, 0, 0, 0], [1, 0, 1, 0, 0, 0, 0], [1, 1, 0, 0, 0, 1, 0], [0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1, 0]]
[['A', 'B', 'C', 'F', 'G'], ['D', 'E']]
distance of these two points is 2
diameter of sub_map ['A', 'B', 'C', 'F', 'G'] is 3
diameter of sub_map ['D', 'E'] is 1
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值