最小生成树(MST)模板

本文详细介绍了两种经典的最小生成树算法——Prim算法和Kruskal算法。Prim算法通过选择距离最近的顶点来逐步构建生成树,而Kruskal算法则是按边的权重从小到大排序,依次加入不构成环的边。这两种算法都广泛应用于图论中解决网络设计等问题。

1:Prim

const int INF = 2000000000;  
#define MAXN 1001
typedef int elem_t;        
                    
/* 1开始编号,n为点数,-INF为不能为生成树*/
elem_t prim(elem_t graph[MAXN][MAXN], int n) 
{
    bool visit[MAXN]={0};
    int mark;
    elem_t dis[MAXN];
    elem_t ans = 0;
	elem_t minnum;
    int i, j;
    visit[1] = 1;
    for(i = 1;i <= n;i ++)
        dis[i] = graph[1][i];
    for (i = 1; i < n; i ++)
    {
        minnum = INF;
		mark = -1;
        for(j = 1;j <= n;j ++)
        {

            if(!visit[j] && dis[j] < minnum)
            {
                minnum = dis[j];
                mark = j;
            }
        }
		if (mark == -1)
			return -INF;
        visit[mark] = true;                       
        ans += minnum;
        for(j = 1;j <= n;j ++)
        {
            if(!visit[j] && graph[mark][j] < dis[j])
                dis[j] = graph[mark][j];
        }

    }
    return ans;
}

2:Kruscal

const int INF = 2000000000;  
const int N   = 0xfffff;
#define MAXN 1001
typedef int elem_t; 

int p[N], r[N];
int find(int x)
{	
	return p[x] == x ? x : p[x] = find( p[x] );	
}

void merge(int x,int y)
{
    int fx,fy;
    fx = find(x);
    fy = find(y);
    if(fx != fy) p[fx] = fy;
}

elem_t cmp(const elem_t i,const elem_t j) { return w[i] < w[j];}
elem_t Kruskal(elem_t w[], int u[], int v[],int m)
{
    elem_t ans = 0;
    for(int i = 0; i < m; ++i) p[i] = i;
    sort(p, p + m, cmp);/*间接排序*/ 
    for(int i = 0; i < m; ++i)
    {
        int    e = p[i];
		elem_t x = find( u[e] );
		elem_t y = find( v[e] );
        if(x != y){ ans += w[e]; merge(x,y); }
    } 
    return ans;
}


### 关于最小生成树算法的解题模板 #### Kruskal 算法示例代码 Kruskal 算法的核心思想是通过不断选取权重最小的边来构建最小生成树,同时确保不会形成环路。以下是基于并查集实现的 Kruskal 算法模板: ```python class UnionFind: def __init__(self, n): self.parent = list(range(n)) def find(self, x): if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) return self.parent[x] def union(self, x, y): rootX = self.find(x) rootY = self.find(y) if rootX != rootY: self.parent[rootY] = rootX def kruskal(edges, n): edges.sort(key=lambda edge: edge[2]) # 按照权重从小到大排序 uf = UnionFind(n) mst_weight = 0 mst_edges = [] for u, v, w in edges: if uf.find(u) != uf.find(v): # 如果两个节点不在同一个连通分量中 uf.union(u, v) mst_weight += w mst_edges.append((u, v, w)) if len(mst_edges) != n - 1: # 判断是否构成一棵生成树 return None return mst_edges, mst_weight ``` 上述代码实现了 Kruska 算法的基础逻辑[^2]。 --- #### Prim 算法示例代码 Prim 算法则采用贪心策略逐步扩展已有的生成树集合。以下是基于邻接矩阵实现的 Prim 算法模板: ```python import heapq def prim(graph, start=0): n = len(graph) visited = [False] * n min_heap = [(0, start)] # (weight, node) mst_weight = 0 mst_edges = [] while min_heap: weight, u = heapq.heappop(min_heap) if visited[u]: continue visited[u] = True mst_weight += weight for v, w in enumerate(graph[u]): if not visited[v] and w > 0: heapq.heappush(min_heap, (w, v)) mst_edges.append((u, v, w)) if sum(visited) != n: # 判断是否所有节点都被访问过 return None return mst_edges, mst_weight ``` 此代码展示了如何利用堆优化的方式加速 Prim 算法的执行效率[^1]。 --- #### 示例应用 假设有一个无向加权图表示如下(邻接表形式),可以通过调用以上函数解决最小生成树问题: 输入样例: ```plaintext edges = [ (0, 1, 7), (0, 3, 5), (1, 2, 8), (1, 3, 9), (2, 3, 7), (2, 4, 5), (3, 4, 15), (3, 5, 6), (4, 5, 8), (4, 6, 9), (5, 6, 11) ] n = 7 # 节点数 m = len(edges) # 边数 ``` 运行 `kruskal(edges, n)` 或者将 `graph` 构建为邻接矩阵后运行 `prim(graph)` 即可得到对应的最小生成树及其总权重[^3]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值