• 最小生成树


    最小生成树


    Prim

    Prim算法流程

    • 随意选取一个点作为已访问集合的第一个点,并将所有相连的边加入最小堆中
    • 从堆中找到最小的连接集合内和集合外点的边,将边加入最小生成树中
    • 将集合外点标记为已访问,并将连边加入堆
    • 重复以上过程直到所有点都在访问集合中

    代码

    //Prim
    #include <bits/stdc++.h>
    
    #define pr pair<int, int>
    #define mk make_pair
    
    using namespace std;
    
    const int N = 1e5 + 1;
    
    struct Node{
    	int v,w,nxt;
    	Node(){};
    	Node(int _v, int _w, int _nxt) : v(_v), w(_w), nxt(_nxt){};
    }edge[N << 2]; 
    
    int n,m,top,cnt,cost;
    int vis[N],head[N],dist[N];
    
    void addedge(int u, int v, int w){
    	edge[++top].v = v;
    	edge[top].w = w;
    	edge[top].nxt = head[u];
    	head[u] = top;
    }
    
    priority_queue<pr, vector<pr>, greater<pr> > q;
    void prim(){
    	for(int i = 1; i <= n; ++i) dist[i] = 0x7fffffff;
    	dist[1] = 0;
    	q.push(mk(dist[1], 1));
    	while(!q.empty()){
    		int u = q.top().second;
    		int d = q.top().first; q.pop();
    		if(vis[u]) continue;
    		vis[u] = 1;
    		cnt += 1;
    		cost += d;
    		for(int i = head[u]; i; i = edge[i].nxt){
    			int v = edge[i].v;
    			int w = edge[i].w;
    			if(w < dist[v] && !vis[v]) // 判断的优化 
    				dist[v] = w,
    					q.push(mk(dist[v], v));
    		}
    		
    	}
    }
    
    int main(){
    	cin >> n >> m;
    	for(int i = 1, u, v, w; i <= m; ++i) cin >> u >> v >> w, addedge(u, v, w), addedge(v, u, w);
    	prim();
    	cnt == n ? printf("%d", cost) : printf("orz");
    	return 0;
    }
    

    Kruskal

    Kruskal算法流程

    • 将边按照权值排序
    • 依次枚举每一条边,若连接的两点不连通则加入最小生成树中
    • 使用并查集维护连通性

    代码

    //Kruskal
    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e5 + 1;
    
    struct Node{
    	int u,v,w;
    	Node(){};
    	Node(int _u, int _v, int _w) : u(_u), v(_v), w(_w){};
    }node[N << 1];
    
    int n,m,cnt,cost;
    int fa[N];
    
    int find(int x){return x == fa[x] ? x : fa[x] = find(fa[x]);}
    
    bool cmp(Node a, Node b){return a.w < b.w;}
    
    void Kruskal(){
    	for(int i = 1; i <= n; ++i) fa[i] = i;
    	sort(node + 1, node + m + 1, cmp);
    	for(int i = 1; i <= m; ++i){
    		int fu = find(node[i].u);
    		int fv = find(node[i].v);
    		if(fu == fv) continue;
    		if(cnt == n - 1) return ; 
    		++cnt, cost += node[i].w;
    		fa[fv] = fu;
    	}
    }
    
    int main(){
    	cin >> n >> m;
    	for(int i = 1; i <= m; ++i) cin >> node[i].u >> node[i].v >> node[i].w;
    	Kruskal();
    	cnt == n - 1 ? printf("%d", cost) : printf("orz");
    	return 0;
    }
    
  • 相关阅读:
    Socket
    UIView的layoutSubviews和drawRect方法何时调用
    断点续传
    IOS后台执行
    应用程序的状态
    ASIHTTPRequest的使用
    XCode5 使用AutoLayout情况下改变控件的 方法
    从指定的view中截图 返回UIImage
    找到当前视图的父视图控制器
    07.网络总结(面试方面)
  • 原文地址:https://www.cnblogs.com/Adventurer-H/p/11274855.html
Copyright © 2020-2023  润新知