LeetCode 1135. 最低成本联通所有城市(最小生成树+排序+并查集)

1. 题目

想象一下你是个城市基建规划者,地图上有 N 座城市,它们按以 1 到 N 的次序编号。

给你一些可连接的选项 conections,其中每个选项 conections[i] = [city1, city2, cost] 表示将城市 city1 和城市 city2 连接所要的成本。(连接是双向的,也就是说城市 city1 和城市 city2 相连也同样意味着城市 city2 和城市 city1 相连)。

返回使得每对城市间都存在将它们连接在一起的连通路径(可能长度为 1 的)最小成本
该最小成本应该是所用全部连接代价的综合。如果根据已知条件无法完成该项任务,则请你返回 -1。

示例 1:
在这里插入图片描述

输入:N = 3, conections = [[1,2,5],[1,3,6],[2,3,1]]
输出:6
解释:
选出任意 2 条边都可以连接所有城市,我们从中选取成本最小的 2 条。

示例 2:
在这里插入图片描述

输入:N = 4, conections = [[1,2,3],[3,4,4]]
输出:-1
解释: 
即使连通所有的边,也无法连接所有城市。
 
提示:
1 <= N <= 10000
1 <= conections.length <= 10000
1 <= conections[i][0], conections[i][1] <= N
0 <= conections[i][2] <= 10^5
conections[i][0] != conections[i][1]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/connecting-cities-with-minimum-cost
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题

图Graph–最小生成树

1. Kruskal

  • 将边的权值排序,小的先遍历,用并查集检查两个顶点是否合并了,没有合并则将该边加入生成树
  • 也可以使用优先队列实现(相当于排序)
class dsu
{
	vector<int> f;
public:
	dsu(int n)
	{
		f.resize(n);
		for(int i = 0; i < n; ++i)
			f[i] = i;
	}
	void merge(int a, int b)
	{
		int fa = find(a);
		int fb = find(b);
		f[fa] = fb;
	}
	int find(int a)
	{
		int origin = a;
		while(a != f[a])
		{
			a = f[a];
		}
		return f[origin] = f[a];
	}
};

class Solution {
public:
    int minimumCost(int N, vector<vector<int>>& connections) {
    	dsu u(N+1);
    	sort(connections.begin(), connections.end(),[&](auto a, auto b){
    		return a[2] < b[2];//距离短的边优先
    	});
    	int edge = 0, p1, p2, dis, total = 0;
    	for(int i = 0; i < connections.size(); ++i)
    	{
    		p1 = connections[i][0];
    		p2 = connections[i][1];
    		dis = connections[i][2];
    		if(u.find(p1) != u.find(p2))//两个还未链接
    		{
    			u.merge(p1,p2);
    			edge++;
    			total += dis;
    		}
    		if(edge == N-1)
    			break;
    	}
    	return edge==N-1 ? total : -1;
    }
};

1504 ms 158.6 MB

2. prim

  • 把一个初始顶点的所有边加入优先队列
  • 取出最短的边,把这条边的另一个顶点相关的边加入队列
  • 再取出最小的边,重复下去,直到所有顶点加入过了
struct cmp
{
	bool operator()(const pair<int,int>& a, const pair<int,int>& b) const
	{
		return a.second > b.second;//小顶堆, 距离小的优先
	}
};
class Solution {
public:
    int minimumCost(int N, vector<vector<int>>& connections) {
		vector<bool> vis(N+1, false);
    	vector<vector<pair<int,int>>> edges(N+1,vector<pair<int,int>>());
    	for(auto& c : connections)
        {
            edges[c[0]].push_back({c[1],c[2]});
            edges[c[1]].push_back({c[0],c[2]});
        }
    	priority_queue<pair<int,int>, vector<pair<int,int>>, cmp> q;
    	int to, distance, total = 0, edge = 0;
        vis[1] = true;
        for(auto& e : edges[1])
            q.push(e);           
    	while(!q.empty())
    	{
    		to = q.top().first;
    		distance = q.top().second;
    		q.pop();
    		if(!vis[to])
            {
                vis[to] = true;
                total += distance;
                edge++;
                if(edge == N-1)
                    return total;
                for(auto& e : edges[to])
                    q.push(e);           
            }
    	}
    	return -1;
    }
};

492 ms 40.9 MB


我的CSDN博客地址 https://michael.blog.csdn.net/

长按或扫码关注我的公众号(Michael阿明),一起加油、一起学习进步!
Michael阿明

猜你喜欢

转载自blog.csdn.net/qq_21201267/article/details/107796632