最小生成树-加边法


一、最小生成树是什么?

最小生成树是图论中一个经典的问题,是指一个连通图中如何做到保留n-1条边并且权值和最小的同时依旧是连通图。

当然,如果是不连通的图,也可以在每个连通分支都生成一颗最小生成树,那么这个生成出来的n个最小生成树也可以看成是“最小生成森林”

二、加边法

最小生成树有两种经典算法,一种是加点法,一种是加边法。

加边法相对而言更容易理解,也就是每回找最小权值的边,如果该边与之前的边不形成回路,则添加该边,直到找到了n-1条边。

所以加边法的重点在于如何判断是否形成回路,在这种情况下,用并查集判环是一个好方法,不知道并查集的话自己去网上找找吧

加边法代码

package 图论.最小生成树;

import java.util.*;

class edgnode implements Comparable<edgnode>{
    int a,b;
    double weight;

    public edgnode() {
    }

    public edgnode(int a, int b, double weight) {
        this.a = a;
        this.b = b;
        this.weight = weight;
    }

    @Override
    public int compareTo(edgnode o) {
        if(this.weight<o.weight){
            return -1;  //返回false
        }else {
            return 1;
        }
    }
}

class g_node{
    int to;
    double weight;

    public g_node() {
    }

    public g_node(int to, double weight) {
        this.to = to;
        this.weight = weight;
    }
}
class treegraph{
    int Maxsize=100;
    int vernum=0;
    //顶点集
    char[] vertex=new char[Maxsize];
    //邻接表
    Vector<g_node>[] tree=new Vector[Maxsize];
    //顶点与下标对应关系
    Map<Character,Integer> map=new HashMap<>();

    void Initvec(int n){
        for (int i = 1; i <= n; i++) {
            tree[i]=new Vector<>();
        }
    }

}



public class kruskal_elne {
    static int Maxsize=100;
    static treegraph graph = new treegraph();
    public static void main(String[] args) {
        PriorityQueue<edgnode> queue=new PriorityQueue<>();
        Scanner scanner = new Scanner(System.in);


        int n,m;
        n=scanner.nextInt();
        m=scanner.nextInt();
        graph.Initvec(n);


        for (int i = 1; i <=n ; i++) {
            char c=(char)('A'+i-1);
            graph.vertex[i]=c;
            graph.map.put(c,i);
            f[i]=i;
        }

        //边集输入
        for (int i = 0; i < m; i++) {
            int a=scanner.nextInt();
            int b=scanner.nextInt();
            double weight=scanner.nextDouble();
            queue.add(new edgnode(a,b,weight));


        }

        int count=0;
        for (int i = 0; i < m; i++) {
            edgnode poll = queue.poll();
            int x = find(poll.a);
            int y = find(poll.b);
            if(x!=y){
                count++;
                f[x]=y;

                //无向图,加两条边
                graph.tree[poll.a].add(new g_node(poll.b,poll.weight));
                graph.tree[poll.b].add(new g_node(poll.a,poll.weight));
            }

            if(count==n-1){
                break;
            }
        }
        dfs(1);
    }

    static int vis[] =new int[Maxsize];
    static void dfs(int i) {
        vis[i]=1;
        for (int j = 0; j < graph.tree[i].size(); j++) {
            g_node g_node = graph.tree[i].get(j);
            int to=g_node.to;
            double weight=g_node.weight;
            if(vis[to]==0){
                System.out.println(graph.vertex[i]+" to "+graph.vertex[to]+":"+weight);
                dfs(g_node.to);
            }
        }
    }

    static int[] f=new int[Maxsize];
    static int find(int x){
        return f[x]==x?x:(f[x]=find(f[x]));
    }
    //merge函数就不写出来了,直接用



}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值