📜  门| GATE-IT-2004 |问题 29(1)

📅  最后修改于: 2023-12-03 15:28:46.069000             🧑  作者: Mango

门 GATE-IT-2004 问题 29

这是一道关于算法和图论的问题,主要考察对图的遍历和最小生成树算法的掌握。

题目描述

给定一个无向图,每个节点都有一个名称和正整数权值。找到一棵生成树,使得该树上节点的权值和最小,并且树的根节点为给定的节点。

输入格式

第一行包含一个整数 $n$,表示图中节点的数量。

接下来 $n$ 行,每行包含一个字符串和一个整数,分别表示节点名称和节点权值。

接下来一行包含一个整数 $m$,表示边的数量。

接下来 $m$ 行,每行包含两个字符串和一个整数,分别表示边所连接的两个节点的名称和边的权值。

最后一行包含一个字符串,表示树的根节点。

输出格式

输出一行,包含树上节点的权值和。

样例输入
5
A 1
B 3
C 4
D 2
E 1
6
A B 2
A C 3
B D 4
C D 5
D E 1
C E 4
A
样例输出
6
解题思路

使用 Prim 算法求解最小生成树,Prim 算法和 Kruskal 算法是最经典的求解最小生成树的算法。

Prim 算法是以一个点为起点,选择一个最小权值的连通边添加到树上,然后逐个添加连通点,最终构成一棵生成树。

Kruskal 算法是把边按权值从小到大进行排序,依次加入这些边,直到在图中形成了一棵生成树为止。

参考代码
def get_weight(node):
    """获取节点权值"""
    return node[1]

def prim(graph, root_node):
    """Prim算法求解最小生成树"""
    # 初始化节点
    nodes = list(graph.keys())
    visited = {node: False for node in nodes}
    heap = [(get_weight(node), node) for node in graph[root_node]]
    visited[root_node] = True
    # 运行算法
    total_weight = 0
    while heap:
        weight, node = heapq.heappop(heap)
        if not visited[node]:
            total_weight += weight
            visited[node] = True
            for neighbor in graph[node]:
                if not visited[neighbor]:
                    heapq.heappush(heap, (get_weight(neighbor), neighbor))
    return total_weight

if __name__ == '__main__':
    # 读取输入
    n = int(input().strip())
    nodes = [input().strip().split() for _ in range(n)]
    m = int(input().strip())
    edges = [input().strip().split() for _ in range(m)]
    root = input().strip()
    # 构建图
    graph = {node[0]: [] for node in nodes}
    for edge in edges:
        graph[edge[0]].append((edge[1], int(edge[2])))
        graph[edge[1]].append((edge[0], int(edge[2])))
    # 运行算法,并输出结果
    print(prim(graph, root))

该代码实现了 Prim 算法求解最小生成树,其中 get_weight(node) 函数用于获取节点的权值,prim(graph, root_node) 函数用于求解以 root_node 为根节点的最小生成树的总权值。