[最小生成树] leetcode 1135 Connecting Cities With Minimum Cost

problem: https://leetcode.com/contest/biweekly-contest-5/problems/connecting-cities-with-minimum-cost/ 

      双周赛题目。此题就是没有什么变化的最小生成树,以下给出两种经典解法:

 

(1).并查集

        首先假设所有的顶点都是一棵单独的树,之后依次选择权重最小的边,使得它连接两棵不同的树,并将两棵树合并为一棵树。当选择了N - 1条边(只剩下一棵树)的时候,意味着得到了最小生成树。

struct edge
{
    int vertex1;
    int vertex2;
    int value;
    edge(int v1, int v2, int val) :vertex1(v1), vertex2(v2), value(val) { }
    friend bool operator<(const edge& e1, const edge& e2)
    {
        return e1.value > e2.value;
    }
};

class Solution {
public:
    vector<int> nums;
    int Find(int x)
    {
        while(x != nums[x])
        {
            x = nums[x];
        }
        return x;
    }
    void Union(int x, int y)
    {
        int px = Find(x);
        int py = Find(y);
        if(px != py)
        {
            nums[px] = py;
        }
    }
    bool InSameSet(int x,int y)
    {
        int px = Find(x);
        int py = Find(y);
        return px == py;
    }
    int minimumCost(int N, vector<vector<int>>& conections) {
        
        priority_queue<edge> pq;
        
        nums.resize(N + 1);
        for(int i = 1; i <= N; i++)
        {
            nums[i] = i;
        }
     
        for(int i = 0; i < conections.size();i++)
        {
            int v1 = conections[i][0];
            int v2 = conections[i][1];
            int val = conections[i][2];

            pq.push(edge(v1, v2, val));
        }
        
        int res = 0;
        int edgeNum = 0;
        while(true)
        {
            if(pq.empty()) return -1;
            edge cur = pq.top();
            pq.pop();
            
            if(InSameSet(cur.vertex1, cur.vertex2))
            {
                continue;
            }
            res += cur.value;
            edgeNum++;
            if(edgeNum == N - 1) return res;
            Union(cur.vertex1, cur.vertex2);
        }
        return res;       
    }
};

 

(2) 宽度优先搜索

        从一个空集合开始,加入任一顶点,并找到该集合中顶点连接的权重最小的边,把该边连接的点也加入集合。直到所有的点都加入了集合,意味着找到了最小生成树。

class Solution {
public:
    vector<unordered_map<int,int>> graph;
    int minimumCost(int N, vector<vector<int>>& conections) {
        graph.resize(N + 1);
     
        for(int i = 0; i < conections.size();i++)
        {
            int v1 = conections[i][0];
            int v2 = conections[i][1];
            int val = conections[i][2];

            if(graph[v1].find(v2) != graph[v1].end())
            {
                graph[v1][v2] = min(graph[v1][v2], val);
                graph[v2][v1] = min(graph[v2][v1], val);
            }
            else
            {
                graph[v1][v2] = val;
                graph[v2][v1] = val;               
            }
        }
        
        priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> pq;

        for(int i = 1;i <= N;i++)
        {
            if(graph[i].size() == 0)
            {
                 return -1;
            }
        }
        vector<bool> visit(N + 1, false);

        pq.push({0,1});
        
        int res = 0;
        int count = 0;
        while(!pq.empty())
        {
            auto cur = pq.top();
            pq.pop();
            if(visit[cur.second]) continue;
           
            res += cur.first;
            visit[cur.second] = true;
            count++;
            
            
            if(count == N) break;
            for(auto& neighbor : graph[cur.second])
            {
                if(!visit[neighbor.first])
                {
                    pq.push({neighbor.second, neighbor.first});
                }
            }   
            
        }
       
        if(count != N) return -1;
        
        return res;
    }
};

 

转载于:https://www.cnblogs.com/fish1996/p/11269623.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值