精华内容
下载资源
问答
  • 最小生成树的两种算法(Prim和Kruskal) 最小生成树的两种算法(Prim和Kruskal) 使用java语言实现Prim算法和Kruskal算法 一、Prim(选择点) public static void prim(int n, double[][] G) { //n为顶点数,G为...

    最小生成树的两种算法(Prim和Kruskal)

    最小生成树的两种算法(Prim和Kruskal)

    使用java语言实现Prim算法和Kruskal算法
    

    一、Prim(选择点)

     public static void prim(int n, double[][] G) {  //n为顶点数,G为邻接矩阵
            double[] MiniWeight = new double[n + 1];  //存储各结点到S集合的最小边的权
            int[] connectedNode = new int[n + 1];  //代表与S集合相连的最小权边的点,connectedNode[i]表示i在S集合,且其值为与i结点相连的最小边的结点的编号
            boolean[] selected = new boolean[n + 1];  //selected[i] == true代表i点在S集合中
            int totalWeight = 0;//总权重
            double[][] MiniTree = new double[n+1][n+1];//最后生成的树
            
            selected[1] = true;  //1为初始顶点
            for(int i = 2; i <= n; i++) {  //初始化辅助数组
                MiniWeight[i] = G[1][i];
                connectedNode[i] = 1;
                selected[i] = false;
            }
            for(int i=0; i<=n; i++) {
                for(int j=0; j<=n; j++) {
            	MiniTree[i][j] = 0;            
                }
            }
            
            System.out.println("S集合初始结点:1" );
            for(int i = 1; i < n; i++) {//寻找到S集合的最小的边
                double min = Float.MAX_VALUE;
                int j = 1;
                for(int k = 2; k <= n; k++) {
                    if((MiniWeight[k] < min) && (!selected[k])) {//根据最小边加入新点
                        min = MiniWeight[k];
                        j = k;
                    }
                }
                totalWeight += min;
                System.out.print("S集合加入结点" + j + "\t");//新加入点的j和与j相连的点
                System.out.print("加入边:" + connectedNode[j] + "---" + j + "\t");
                System.out.println("边的权重为:" + min);
                
                selected[j] = true;//加入新点j
                MiniTree[j][connectedNode[j]] = min;
                MiniTree[connectedNode[j]][j] = min;
                
                for(int k = 2; k <= n; k++) {
                    if((G[j][k] < MiniWeight[k]) && !selected[k]) {//根据新加入的点j,另求各结点到S集合的最小边的权
                        MiniWeight[k] = G[j][k];
                        connectedNode[k] = j;
                    }
                }
            }
            System.out.println("最小权重为:" + totalWeight);
            System.out.println("最小生成树为:");
            for(int i=0; i<=n; i++) {
                for(int j=0; j<=n; j++) {
            	System.out.print(MiniTree[i][j] + "\t");            
                }
                System.out.println();
            }
        }
    

    二、Kruskal(选择边)

    class Edge{
        int startNode;
        int endNode;
        int weight;
    }
    
     //Kruskal算法,添加边
        public static void Kruskal(int[][] G, int n) {
    	int[][] MiniTree = new int[n][n];//最后生成的树
    	Edge[] edge = sort(convertEdge(G)); //排序过的边的集合
    	List<Edge> edgeList = new ArrayList<Edge>();//选择的边的集合
    	for(int i=0; i<edge.length; i++) {
    	    if(!isRing(edge[i], edgeList)){//不是环
    		edgeList.add(edge[i]);
    	    }
    	    if(edgeList.size() == n-1)//结束
    		break;
    	}
    	
    	System.out.println("选择的边有:");
    	for(Edge i : edgeList) {
    	   System.out.print("边" + i.startNode+ " "+ i.endNode + "\t"); 
    	   MiniTree[i.startNode-1][i.endNode-1] = i.weight;
    	   MiniTree[i.endNode-1][i.startNode-1] = i.weight;
    	}
    	System.out.println();
    	System.out.println("生成的树为:");
    	for(int i=0; i<n; i++) {
    	    for(int j=0; j<n; j++) {
    		System.out.print(MiniTree[i][j] + "\t");
    	    }
    	    System.out.println();
    	}
    	
        }
        
        public static Edge[] sort(Edge[] edge) {//按照边的权重排序
    	for(int i=0; i<edge.length-1; i++) {
    	    for(int j=i+1; j<edge.length; j++) {
    		if(edge[i].weight > edge[j].weight) {
    		    Edge temp = edge[i];
    		    edge[i] = edge[j];
    		    edge[j] = temp;
    		}
    	    }
    	}
    	return edge;
        }
        
        public static Edge[] convertEdge(int[][] G) {//将邻接矩阵转换成边的集合,没有重复边
    	int n = G.length;
    	int max = (n*(n-1))/2;//边数量的最大值
    	int count = 0;
    	for(int i=0; i<n; i++) {
    	    for(int j=0; j<n; j++) {
    		if(G[i][j] == 0) count++;//没有的边的数量
    	    }
    	}
    	int num = max - ((n-count)/2);//计算出矩阵中有多少条边
    	Edge[] edge = new Edge[num/2];
    	int index = 0;
    	for(int i=0; i<n-1; i++) {
    	    for(int j=i+1; j<n; j++) {
    		if(G[i][j] != 0) {
    		    Edge temp = new Edge();
    		    temp.startNode = j+1;
    		    temp.endNode = i+1;
    		    temp.weight = G[i][j];
    		    edge[index] = temp;
    		    index++;
    		}
    	    }
    	}
    	return edge;
        }
        
        //判断是否为环,edge是要加入的边,edgeList是选择的边的集合
        public static boolean isRing(Edge edge, List<Edge> edgeList) {
    	boolean result = false;
    	for(int i=0; i<edgeList.size(); i++) {
    	    if(edgeList.get(i).startNode==edge.startNode || edgeList.get(i).endNode==edge.startNode) {
    		 for(int j=i+1; j<edgeList.size(); j++) {
    		     if(edgeList.get(j).startNode==edge.endNode || edgeList.get(j).endNode==edge.endNode) {
    			 if(edgeList.get(j).startNode==edgeList.get(i).startNode ||
    		            edgeList.get(j).startNode ==edgeList.get(i).endNode ||
    		            edgeList.get(j).endNode == edgeList.get(i).startNode||
    		            edgeList.get(j).endNode == edgeList.get(i).endNode) {
    			     result = true;
    			 }
    		     }
    		 }
    	    }
    	}
    	return result;
        }
        
    
    

    测试实例

    Prim

    double m = Double.MAX_VALUE;
            double[][] weight = {
            	            {0, 0, 0, 0, 0, 0, 0},
                                {0, m, 6, 1, 5, m, m},
                                {0, 6, m, 5, m, 3, m},
                                {0, 1, 5, m, 5, 6, 4},
                                {0, 5, m, 5, m, m, 2},
                                {0, m, 3, 6, m, m, 6},
                                {0, m, m, 4, 2, 6, m}
                                };
            MiniTree.prim(weight.length - 1, weight);
    

    结果:
    在这里插入图片描述
    Kruskal

    int[][] weight2 = {
    	            	     { 0, 6, 1, 5, 0, 0},
    	            	     { 6, 0, 5, 0, 3, 0},
    	            	     { 1, 5, 0, 5, 6, 4},
    	            	     { 5, 0, 5, 0, 0, 2},
    	            	     { 0, 3, 6, 0, 0, 6},
    	            	     { 0, 0, 4, 2, 6, 0}
                    	    };
    	MiniTree.Kruskal(weight2, weight2.length);
    

    结果:
    在这里插入图片描述

    展开全文
  • 二、最小生成树的概念 三、普里姆算法(Prim)构造最小生成树 四、 克鲁斯卡尔算法(Kruskal)构造最小生成树 一、生成树的概念: 一个连通图的生成树是一个极小连通子图,它含有图中全部n个顶点和构成一...

    文章目录

    一、生成树的概念

    二、最小生成树的概念

    三、普里姆算法(Prim)构造最小生成树

    四、 克鲁斯卡尔算法(Kruskal)构造最小生成树

    一、生成树的概念:

    一个连通图的生成树是一个极小连通子图,它含有图中全部n个顶点和构成一颗树的(n-1)条边。

    在这里插入图片描述

    可以用深度优先遍历、广度优先遍历生成树:

    在这里插入图片描述
    在这里插入图片描述

    二、最小生成树的概念:

    对于带权连通图G(每条边上的权均为大于零的实数),可能有多棵不同生成树。

    • 对于带权连通图G(每条边上的权均为大于零的实数),可能有多棵不同生成树。
    • 每棵生成树的所有边的权值之和可能不同
    • 其中权值之和最小的生成树称为图的最小生成树

    三、普里姆算法(Prim)

    普里姆算法是一种构造性算法,用于构造最小生成树

    Prim算法更适合稠密图求最小生成树

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    四、克鲁斯卡尔算法(Kruskal)

    • 一种求带权无向图的最小生成树的构造性算法
    • 按权值的递增次序选择合适的边来构造最小生成树的方法。
    Kruskal算法更适合稀疏图求最小生成树

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • [Sicily 1090]使用普里姆算法、克鲁斯卡尔算法求最小生成树的代码实现。

    (1)问题描述:

    [Sicily 1090 Highways]

    政府建公路把所有城市联系起来,使得公路最长的边最短,输出这个最长的边。


    (2)基本思路:

    使得公路最长的边最短其实就是要求最小生成树。


    (3)代码实现:

    普里姆算法:

    #include <iostream>
    using namespace std; 
    #define MAX_DIS 1000000
    int main()
    {
    	int T;
    	cin >> T;
    	for(int t = 1; t <= T; t++)
    	{
    		int n;
    		cin >> n;
    		int mat[n + 1][n + 1];
    		int d[n + 1];
    		int v[n + 1];
    		for(int i = 1; i <= n; i++)
    		{
    			fill(mat[i], mat[i] + n + 1, MAX_DIS);
    		}
    		for(int i = 1; i <= n; i++)
    		{
    			for(int j = 1; j <= n; j++)
    			{
    				cin >> mat[i][j];
    			}	
    		}	
    		int max_length = 0;
    		fill(d, d + n + 1, MAX_DIS);
    		fill(v, v + n + 1, 0);
    		d[1] = 0;
    		for(int i = 1; i <= n; i++)
    		{
    			int min = MAX_DIS;
    			int min_index = -1;
    			for(int j = 1; j <= n; j++)
    			{
    				if(d[j] < min && v[j] == 0)
    				{
    					min = d[j];
    					min_index = j;
    				}
    			}
    			//加入点min_index 
    			v[min_index] = 1;
    			if(min > max_length)
    				max_length = min;
    			for(int j = 1; j <= n; j++)
    			{
    				if(v[j] == 0 && mat[min_index][j] < d[j])
    				{
    					d[j] = mat[min_index][j];
    				}
    			}
    		}
    		cout << max_length << endl;
    		if(t != T)
    			cout << endl;
    	} 
    	return 0;
    }


    克鲁斯卡尔算法:

    #include <iostream>
    #include <algorithm>
    using namespace std;
    int u[200000];//左端点
    int v[200000];//右端点
    int w[200000];//权重
    int e[200000];//辅助排序,排完序后,e[0]所存的值是使得权重w[e[0]]最小的
    int p[501];//并查集 
    bool cmp(int i, int j)
    {
    	return w[i] < w[j];
    }
    int find(int x)
    {
    	return (p[x] == -1)? x: p[x] = find(p[x]);
    }
    int _union(int x, int y)
    {
    	p[y] = x;
    }
    int main()
    {
    	int T;
    	cin >> T;
    	for(int t = 1; t <= T; t++)
    	{
    		int n;
    		cin >> n;
    		int count = 0;//表示一共有几条边 
    		int weight;
    		for(int i = 1; i <= n; i++)
    		{
    			for(int j = 1; j <= n; j++)
    			{
    				cin >> weight;
    				if(weight != 0)
    				{
    					if(i < j)//只需要存其中一条边
    					{
    						u[count] = i;
    						v[count] = j;
    						w[count] = weight;
    						count++;					
    					}
    				}
    			}	
    		}
    		
    		//思想:把边排序 
    		for(int i = 0; i < count; i++)
    			e[i] = i;
    		sort(e, e + count, cmp);
    		//并查集初始化每个点的根结点为自己(-1) 
    		for(int i = 1; i <= n; i++)
    			p[i] = -1;
    		
    		int min_w_index;
    		int x;
    		int y;
    		int edge = 0;
    		for(int i = 0; i < count; i++)
    		{
    			min_w_index = e[i];
    			x = find(u[min_w_index]);
    			y = find(v[min_w_index]);
    			//若左端点和右端点的根结点一样,则加入的边必然导致环 
    			if(find(x) != find(y))//根结点不同的时候加入 
    			{
    				edge++;
    				_union(x, y);
    			}
    			if(edge == n - 1)
    			{
    				cout << w[min_w_index] << endl;	
    				break;			
    			}
    		}
    		if(t != T)
    			cout << endl;
    	} 
    }
      


    展开全文
  • Problem Description省政府“畅通工程”目标是使全省任何个村庄间都可以实现公路交通(但不一定有直接公路相连,只要能间接通过公路可达即可)。经过调查评估,得到统计表中列出了有可能建设公路若干条...
    Problem Description
    省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
     

    Input
    测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N
    行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
     

    Output
    对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
     

    Sample Input
    3 3 1 2 1 1 3 2 2 3 4 1 3 2 3 2 0 100
     

    Sample Output
    3 ?

     最小生成树之prim算法。。。。


    #include<iostream>  
    using namespace std;  
    #include<string.h>  
    #define maxn 0x7fffffff  
    int mat[105][105],n,m;  
    void prim()  
    {  
        int mst[105],i,j,minn,pos,low[105],sum=0;  
        for(i=2;i<=m;i++)  
        {  
          low[i]=mat[1][i];  
          mst[i]=1;  
        }  
        mst[i]=0;  
        for(j=2;j<=m;j++)  
        {   minn=maxn;  
             pos=0;  
            for(i=2;i<=m;i++)  
            {  
                if(minn>low[i]&&low[i]!=0)  
                {  
                    minn=low[i];  
                    pos=i;  
                }  
            }  
            if(minn==maxn)  
            {  
                cout<<"?\n";  
                return ;  
            }  
        low[pos]=0;  
        sum=sum+minn;  
        for(i=2;i<=m;i++)  
        {  
            if(mat[pos][i]<low[i])//未选择的节点到各已选择的节点的权值 
            {  						//谁小与谁相连(前提是原本就相同) 
                low[i]=mat[pos][i]; //如图V2和V1,V3都相通。 
                mst[i]=pos;//例如V2选择与V3相连 
            }  
        }  
     }  
       cout<<sum<<endl;  
       return ;  
    }  
     int main()  
     {  
         int i,j,k,cost,i1,j1;  
         while(cin>>n>>m)  
         { if(n==0)break;  
            for(i1=0;i1<105;i1++)  
                for(j1=0;j1<105;j1++)  
                     mat[i1][j1]=maxn;  
             for(k=0;k<n;k++)  
             {  
                 cin>>i>>j>>cost;  
                 mat[i][j]=cost;  
                 mat[j][i]=cost;  
             }  
              prim();  
         }  
         return 0;  
     }  

    kruskal算法。。。。


     //代码与并查集有关 
     #include<iostream>  
     using namespace std;  
     #include<string.h>  
     #include<algorithm>  
     int bin[105],n,m;  
     struct hyf  
     {  
         int x,y,value;  
     }p[105];  
     bool cmp(struct hyf a,struct hyf b)  
     {  
        return a.value<b.value;  
     }  
     int findx(int x)  
     {  
         int r=x;  
         while(r!=bin[r])  
          r=bin[r];  
          return r;  
     }  
     void fun(int x,int y)  
     {  
         int tx,ty;  
         tx=findx(x);  
         ty=findx(y);  
         if(tx!=ty)  
            bin[tx]=ty;  
     }  
     int main()  
     {  
         int i,j,tx,ty,tz;  
         while(cin>>n>>m)  
         {  
             if(n==0)break;  
             for(i=1;i<=m;i++)  
                bin[i]=i;  
             for(i=0;i<n;i++)  
                cin>>p[i].x>>p[i].y>>p[i].value;  
                sort(p,p+n,cmp);  
             int res=m,ans=0;  
             for(i=0;i<n;i++)  
             {  
                 if(res>1)  
                 {  tx=p[i].x;ty=p[i].y;tz=p[i].value;  
                     if(findx(tx)==findx(ty))//判断是否属于同一个集合  
                        continue;  
                     else  
                     {  
                         fun(tx,ty);//把两点连接起来  
                         res--;  
                         ans=ans+tz;  
                     }  
                 }  
             }  
             if(res==1)//判断是否构建成功  
             cout<<ans<<endl;  
             else cout<<"?"<<endl;  
         }  
     }  




    展开全文
  • 两种算法都是用于求带权无向图的最小生成树最小生成树即代价值最小树。 一、Prime算法 通俗又称加点法
  • 传送门布线问题时间限制:1000 ms | 内存限制:65535 KB难度:4描述南阳理工学院要进行用电线路改造,现在校长要求设计师设计出一布线方式,该布线方式需要满足以下条件:1、把所有楼都供上电。2、所用电线...
  • 最小生成树的3个算法

    千次阅读 2015-08-31 11:16:31
    最小生成树——Prim、Kruskal、Sollin(Boruvka) ...对于最小生成树,有两种算法可以解决。一种是Prim算法,该算法时间复杂度为O(n²),与图中边数无关,该算法适合于稠密图,而另外一种是Kruskal,该算法时间
  • 平面连通图是一个二维网络,网络由节点和边组成,比如我随手画了一个:也可以是这样:它并不是一个空间连通图因为他可以拓扑变换成这样:但如果这种图就不行了:这样连通图只能出现在三维空间中,所以无法满足欧拉公式. ...
  • 求次小生成树时,依次枚举用过边,将其去除后再求最小生成树,得出所有情况下最小生成树就是次小生成树。可以证明:最小生成树与次小生成树之间仅有一条边不同。 这样相当于运行m次Kruskal算法。 复杂度O...
  • Prim算法和Kruskal算法是求解最小生成树的两种经典算法,这两个算法都是贪心算法。使用到了MST的一个性质:两个集合之间相连的最短的边一定属于两个集合组成的生成树。该性质的详细证明请见算法导论第23...
  • 最小生成树(Minimum Cost ...普利姆算法是以某顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树的。 思路:假设 N = (P, {E}) 是连通网, TE 是 N上最小生成树中边的集合。算法从 U = {u0}(u0 属于 V), TE = {}
  • 的两种最小生成树算法之C++封装

    千次阅读 2017-08-02 23:19:13
    最小生成树定义:  给定一无向带权图,顶点数是n,要使图连通只需n-1条...两种最小生成树算法: 1、prim算法: 设图G顶点集合为U,首先任意选择图G中一点作为起始点a,将该点加入集合V,再从集合U-V中找到另一点b
  • bool graph_mtx, E>::insert_edge(const T& vert1, const T& vert2, E cost = MAX_COST)//由于权值存在默认值,get_neighbor操作需判断是否等于MAX_COST,否则不能正常取得邻接顶点 { if(this->is_full()) //判满...
  • 用大白话来解释就是,用一个图把所有点都连接起来,而且所有边总权值在所有图中最小。 二、算法 (1)克鲁斯卡尔算法 基本思想: 第一步:把所有边从小到大排序。 第二步:开始选边,每一个边要保证都...
  • 设G = (V,E)是无向连通带权图,即一个网络。E中的每一条边(v,w)的权为c[v][w]。...构造最小生成树的两种方法:Prim算法和Kruskal算法。  一、最小生成树的性质  设G = (V,E)是连通带权图,U是V
  • 最小生成树算法

    2019-08-13 11:20:24
    简介:最小生成树算法一共有两种,分别是kruskal算法和prim算法。也属于贪心算法,它目的就是给定无向图、权值以及顶点,求联通所有边权值和最小。 kruskal算法: 先构造一个只含 n 个顶点、而边集为空子图,...
  • 无向图最小生成树两种做法)

    千次阅读 2020-09-08 12:58:12
    构造网的最小生成树必须解决下面个问题: 1、尽可能选取权值小边,但不能构成回路; 2、选取n-1条恰当边以连通n个顶点; MST性质:假设G=(V,E)是一个连通网,U是顶点V一个非空子集。若(u,v)是一条具有最小...
  • 这个问题就是求最小生成树,有两种经典的算法:prim、kruskal算法 普利姆算法(prim) prim算法的核心思想: 从起点开始,每次都找到该起点权值最小边 将该边另一个顶点加入集合visited,然后找visited集
  • 给定一个无向图,如果它某个子图中任意两个顶点都相互连通并且是一棵树,那么这棵树就叫做生成树,如果边上有权值,那么使得边权和最小生成树叫做最小生成树(MST)。 - 解决MST问题主要会用到两种算法  1. ...
  • 最小生成树算法(C++)

    2021-04-06 17:20:08
    刚把最小生成树的两种算法学习了下,代码参考博主最小生成树算法,博主介绍的很详细,基本掌握了,自己将部分代码段添加了注释,留后续复习用 一、Prime算法 #include<iostream> #include<string> #...
  • 一、最小生成树介绍图结构是一非常重要非线性数据结构,带权图的最小生成树在工程技术,科学管理最优解问题中有着广泛应用。最小生成树:权值和最小生成树最小生成树性质:假设G=(V,E)是个连通图,U是...
  • 最小生成树:  一个有 n 个结点连通图生成树是原图极小连通子图,且包含原图中所有 ... 最小生成树问题一般有以下两种求解方式。 一、Prim算法  参考了Feynman博客   Prim算法通常以邻接矩阵作为...
  • 设A是G的某棵最小生成树的子集,并设C=(Vc,Ec)为森林Ga=(V,A)的一个连通分量,如果边(u,v)是连接C和Ga中某个其他连通分量的一条轻量级边,则(u,v)对于A来说是安全的。 Kruskal算法 在所有的连接颗树的边里...
  • MST(Minimum Spanning Tree,最小生成树)问题有两种通用解法,Prim算法就是其中之一,它是从点方面考虑构建一颗MST。 二、算法描述 大致思想:有一带权连通图G = (U,E),即图G顶点集合为U 、边集为E。...
  • 两种方法,样题 畅通工程 省政府“畅通工程”目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接公路相连,只要能间接通过公路可达即可)。经过调查评估,得到统计表中列出了有可能建设公路若干...
  • 最小生成树(MST):一棵权值最小(树中所有边的权值之和)的生成树。 1.2 算法原理 1.2.1 切分定理 切分定义:图的一切分是将图的所有顶点分为两个非空且不重合的两个集合。横切边是一条连接两个属于不同集合的...
  •  MST(Minimum Spanning Tree,最小生成树)问题有两种通用解法,Prim算法就是其中之一,它是从点方面考虑构建一颗MST,大致思想是:设图G顶点集合为U,首先任意选择图G中一点作为起始点a,将该点加入集合V,...
  • 十七、图算法最小生成树

    千次阅读 2016-04-18 22:08:47
    说白了就是连接所有点然后权值最小的无环连通子图主要有两种算法:Prim算法和Kruskal算法先做一些约定:只考虑连通图(不连通你分开算就行了) 边权重不一定是表示距离 边权重可能是0或者负数(无环,负数就不...
  • 今天和大家介绍构造最小生成树的两种常用算法。01prim 算法构造最小生成树设置两个集合 P 和 Q ,其中 P 用于存放 G 的最小生成树中的顶点,集合 Q 存放 G的最小生成树中的边。令集合 P 的初值为 P ={v1}(假设构...

空空如也

空空如也

1 2 3 4 5 ... 19
收藏数 361
精华内容 144
关键字:

最小生成树的两种算法、