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

        最小生成树MST是在一个图中求出一个连接N个点的树,使得树的N-1条边的权值之和最小。 
        求最小生成树有两种方法:1. prim算法 2.kruskal算法

    prim算法

        贪心思想,将N个点分为两个集合。V(在最小生成树中的点集合)和S-V(不在最小生成树中的点集合),每次从S-V集合中选取 距离集合V中的点的距离最小的点,加入V集合。直到集合S-V为空。 
    实现

    struct Edge{
    	int vertex;
    	int dist;
    	Edge(int v, int d) :
    		vertex(v), dist(d){};
    };
    vector<vector<Edge> > gGraph;
    struct Compare{
    	bool operator()(const Edge& e1, const Edge& e2){
    		return e1.dist > e2.dist;
    	}
    };
    
    bool gVisited[MAX_NODE];
    
    int Prim(int n){	//prim算法加堆优化
    	memset(gVisited, false, sizeof(gVisited));
    	//随便选择一个起点,假设从0开始
    	Edge e(0, 0);
    	int sum_mst = 0;
    	priority_queue<Edge, vector<Edge>, Compare> pq;
    	pq.push(e);
    	while (!pq.empty()){
    		e = pq.top();
    		pq.pop();
    		if (gVisited[e.vertex])
    			continue;
    		gVisited[e.vertex] = true;
    		sum_mst += e.dist;
    		for (int i = 0; i < gGraph[e.vertex].size(); i++){	//将该点连接边都加入到优先队列中,进行下一轮选择
    			pq.push(gGraph[e.vertex][i]);
    		}
    	}
    	return sum_mst;
    }
    

    kruskal算法

        贪心思想。将所有的边进行排序,然后按照边长从小到大的顺序,判断边连接的两点是否已经同时在最小生成树上了,若在,则抛弃该边(为了避免形成环),继续;否则将该边加入最小生成树。 
    实现

    //边的数据结构
    struct Edge{
    	int from;
    	int to;
    	double dist;
    	Edge(int f, int t, double d) :
    		from(f), to(t), dist(d){};
    };
    vector<Edge> gEdges;
    
    //用并查集来判断加入一条边是否会构成环
    int gRoot[MAX_NODE];
    int GetRoot(int c){
    	if (gRoot[c] != c){
    		gRoot[c] = GetRoot(gRoot[c]);
    	}
    	return gRoot[c];
    }
    bool SameRoot(int c1, int c2){
    	int p1 = GetRoot(c1);
    	int p2 = GetRoot(c2);
    	return p1 == p2;
    }
    
    void Union(int c1, int c2){
    	int p1 = GetRoot(c1);
    	int p2 = GetRoot(c2);
    	gRoot[p1] = p2;
    }
    //用于对边进行排序
    bool Compare(const Edge& e1, const Edge& e2){
    	return e1.dist < e2.dist;
    }
    
    
    double Kruskal(int s, int n){
    	double result;
    	for (int i = 0; i < n; i++){
    		gRoot[i] = i;
    	}
    	sort(gEdges.begin(), gEdges.end(), Compare); //无向图的边只存储了 从序号较小的节点指向序号较大的节点
    	int count = 0;
    	for (int i = 0; i < gEdges.size(); i++){
    		Edge& e = gEdges[i];
    		if (SameRoot(e.from, e.to))
    			continue;
    
    		count++;
    		if (count == n - s){ 
    			//从最小生成树中的n-1条边,去掉最大的s-1条边(因为有s个卫星站,相当于s个点,则s-1条边)
    			//,剩下的n-1-s条边中,最大的边长即为所求
    			result = e.dist;
    			return result;
    		}
    		
    		Union(e.to, e.from);
    		//gRoot[gRoot[e.to]] = gRoot[e.from]; //注意合并的时候,将 to 的根更新为 from的根。因为所有的边只存储了从小序号指向大序号
    	}
    	return 0;
    }
    
  • 相关阅读:
    docker容器的本质
    golang 算法题 : 二维数组搜索值
    golang 算法题 : 两数相加
    golang 开源代理
    golang vue 使用 websocket 的例子
    互联网技术部门该如何管理
    大数据清洗第一天
    本周总结
    信息领域热词分析性能分析
    本周总结
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/4867543.html
Copyright © 2011-2022 走看看