算法练习:最小生成树

目录

Prime算法

数据结构

核心代码

Kruskal算法

数据结构

算法思路

核心代码

例题

最小生成树试炼之最短网络

描述

输入 

数据范围

输出 

输入样例 1 

输出样例 1


Prime算法

数据结构

二维数组:

graph[n][n]:存储图

distance[n] :存储正在生成的最小生成树与未连接结点的最小距离

v[n]:存储已加入正在生成的最小生成树的点

核心代码

int Prime(){
    for(int i = 0 ; i < n ; i++){
        //初始化,以结点0为起点,初始化 v 到 u 集合的最小距离
        u_distance[i] = a[0][i] ;
        //初始化 v 集合
        v[i] = 0 ;
    }
    //把结点 0 加入 v 集合
    v[0] = 1 ;
    //最小生成树总路程设为 0 
    int  ans = 0;
    for(int k = 0 ; k < n-1 ; k++){
        //设置 min_pointer 存储 v 到 u 有最短距离的点 , u_min 表示 u 到 v 最短长度
        int min_pointer = -1 , u_min = max ;
        // u 中到 v 最小距离查找
        for(int i = 0 ; i < n ; i++){
            if( !v[i] && u_distance[i] < u_min )
                u_min = u_distance[ min_pointer = i ] ;
        }
        //找到了,加入最小生成树的总路程,把点加入 v
        ans += u_distance[min_pointer] ;
        v[min_pointer] = 1 ;
        //遍历新加入 v 的点到 u 的距离,如果比当前 v 到 u 某个点的距离小,则替换上去
        for(int i = 1 ; i < n ; i++){
            if( !v[i] && u_distance[i] > a[min_pointer][i] )
                u_distance[i] = a[min_pointer][i] ;
        }
    }
    return ans;
}

Kruskal算法

数据结构

结构体: { s 起点序号,e 终点序号 ,w 边的长 }

算法思路

输入边,把边按权值排序

对每条边,查询起点终点是否为同个集合,不是则把改边加入最小生成树中

核心代码

//点的个数
int n = 0 ;
struct edge{
    //出发点s,终点e,长度w
    int s,e,w ;
}edges[max] ;

int cmp_edges(edge a , edge b){
    //定义排序的方法
    return a.w < b.w;
}

void edges_get(){
    int count = 0;
    scanf("%d" , &n) ;
    for(int i = 0 ; i < n ; i++){
        for(int j = 0 ; j < n ; j++){
            int len ;
            scanf("%d" , &len) ;
            if( i < j ){
                edges[count].s = i ;
                edges[count].e = j ;
                edges[count++].w = len;
            }
        }
    }
    sort(edges , edges + n , cmp_edges) ;//把边从小到大排序
}
//用并查集的方法
//父节点数组
int fa[max] = {0} ;
//初始化父节点数组
void init_fa(){
    for(int i = 0 ; i < n ; i++)
        fa[i] = i ;
}
//查询父节点的方法
int find(int a){
    return a == fa[a] ? a : (fa[a] = find(fa[a]));
}
//Kruskal算法
int Kruskal(){
    int ans = 0;
    init_fa() ;
    for(int i = 0 ; i < n ; i++){
        //查询一个边的两个点是否同个集
        //分别查询两个点的父节点
        int x = find (edges[i].s) ;
        int y = find (edges[i].e) ;
        //不同集
        if(x != y){
            //最小权和加上此边
            ans += edges[i].w ;
            //则把终点设置为起点的父节点
            fa[x] = y ;
        }
    }
    return ans;
}

例题

最小生成树试炼之最短网络

描述

经过不懈努力林克已经给他的林克城安了一条高速的网络线路,他想把这条线路共享给其他城市,尤其是塞尔达城。

林克城的编号是1,其他城市的编号是2∼n。

为了使花费最少,他希望用于连接所有的城市的光纤总长度尽可能短。

林克需要根据一份各城市之间连接距离的列表找出能连接所有城市并使所用光纤最短的方案。

输入 

第一行包含一个整数n,表示城市个数。

接下来n行,每行包含n个整数,输入一个对角线上全是0的对称矩阵。
其中第x+1行y列的整数表示连接农场x和农场y所需要的光纤长度。

数据范围

3≤n≤100
每两个城市间的距离均是非负整数且不超过100000。

输出 

输出一个整数,表示所需的最小光纤长度。

输入样例 1 

4
0  4  9  21
4  0  8  17
9  8  0  16
21 17 16  0

输出样例 1

28

题解

这道题貌似有问题,用Kruskal做不了哈哈哈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值