zoukankan      html  css  js  c++  java
  • 最小生成树

    普里姆算法(Prim)

    普里姆算法基本思想:从图中某个顶点V0开始,将V0到其他顶点的所有边当做候选边,重复以下步骤n-1次,使得其他n-1个顶点并入到树中:1、从候选边中挑选出权值最小的边输出,并将该边另一端相接的顶点V并入树中;2、考察所有剩余顶点Vi,如果(V,Vi)的权值比lowcost[Vi]小则用(V,Vi)的权值更新lowcost[Vi]。

    普里姆算法模板

    #define MAXN 101                //定义顶点的最大可达数
    int n, sum;                          //顶点数,权值和
    int map[MAXN][MAXN];         //以邻接矩阵存储权值
    
    void prim()
    {
    	int vset[MAXN];     //记录顶点是否访问过
    	int lowcost[MAXN]; //最小权值记录
    	int i, j;
    	for ( i=0; i<n; i++)
    	{
    		vset[i] = 0;
    		lowcost[i] = map[0][i];
    	}
    	vset[0] = 1;
    	int u, min;
    	for ( i=1; i<n; i++)
    	{
    		min = 100001;
    		for ( j=1; j<n; j++) //从备选边中选出最小边
    		{
    			if ( ! vset[j] && lowcost[j] < min && lowcost[j] > 0)
    			{
    				u = j;
    				min = lowcost[j];
    			}
    		}
    
    		vset[u] = 1;
    		sum += min;
    		for ( j=1; j<n; j++) //更新备选边
    		{
    			if (! vset[j] &&  map[u][j] < lowcost[j] )
    				lowcost[j] = map[u][j];
    		}
    	}
    }
    

    克鲁斯卡尔算法(Kruskal)

    克鲁斯卡尔算法基本思想:将图中边按照从小到大排序,然后从最小边开始扫描,并检测当前边是否是为候选边,即是否该边的并入会构成回路(使用并查集),如果不构成回路,则将该边并入当前生成树中,直到所有边都检测为止。

    克鲁斯卡尔算法模板

    #include <stdio.h>
    #include <queue>
    using namespace std;
    
    const int Maxv =101;
    
    typedef struct
    {
    	int from,to,cost;
    }Node;
    
    bool operator > (Node a,Node b)
    {
    	if( a.cost > b.cost )
    		return true;
    	return false;
    }
    
    int dis[Maxv][Maxv]; //dis以邻接矩阵形式表示一幅图 dis[i][j]为0时表示i点和j点不连通
    int v[Maxv]; //并查集
    
    int getRoot(int a)
    {
        while(a!=v[a]) a=v[a];
        return a;
    }
    
    int main()
    {
    	int sum;
    	priority_queue< Node,vector<Node>,greater<Node> > Q;  //返回最小数
    
    	int vn,i,j;  
    	while( scanf( "%d" , &vn ) != EOF )
    	{
    		//输入图部分
    		for( i = 1 ; i <= vn ; i++ )
    			for( j = 1 ; j <= vn ; j++ )
    				scanf( "%d" , &dis[i][j] );
    		for( i = 1 ; i <= vn ; i++ )   v[i] = i;	
    		while( !Q.empty() )  Q.pop();
    		//把每条边压入堆中
    		for( i = 1 ; i < vn ; i++ )
    			for( j = i+1 ; j <= vn ; j++ )
    				if( dis[i][j] )
    				{
    					Node e;
    					e.from = i , e.to= j , e.cost = dis[i][j];
    					Q.push(e);
    				}
    
    		sum = 0;
    		while( Q.size() != 0 )
    		{
    			Node e;
    			e = Q.top();
    			Q.pop();
    			if( getRoot(e.from) != getRoot(e.to) )
    			{
    				sum += e.cost;
    				v[getRoot(e.from)] = getRoot(e.to);
    			}
    		}
    
    		printf( "%d\n" , sum );    //所需的最小值
    	}
    	
    	return 0;
    }
    
    
  • 相关阅读:
    处处留心皆学问,世事如棋局局新…
    【转载】2017 软件测试行业现状调查报告_From_51testing_On_20180625
    Hello World In Go ...
    C# 易错题整理
    C# 函数
    C# 哈希表,队列,栈
    C# 数组,集合,泛型集合
    C# 如何生成验证码
    C# 年月日时间题+Timespan
    闰年的一个BUG
  • 原文地址:https://www.cnblogs.com/flyoung2008/p/2137381.html
Copyright © 2011-2022 走看看