最小生成树

问题描述

给出一些Connections,即Connections类,找到一些能够将所有城市都连接起来并且花费最小的边。
如果说可以将所有城市都连接起来,则返回这个连接方法;不然的话返回一个空列表。

 注意事项

返回cost最小的连接方法,如果cost相同就按照city1进行排序,如果city1也相同那么就按照city2进行排序。


样例

给出 connections = ["Acity","Bcity",1], ["Acity","Ccity",2], ["Bcity","Ccity",3]

返回 ["Acity","Bcity",1], ["Acity","Ccity",2]


思路

使用优先级队列存储所有的边,再用hash表存储每个节点的根。一开始设置每个节点的根节点为自己。
每次从优先级队列中取出最小的边,若这条边的两个节点的根节点相同,则继续取下一条边;
若根节点不同,则将其中一个根节点的根设置为另一个根节点,这条边同时加入最小生成树。
最后遍历所有的节点,查看所有节点的根节点是否一致,若存在不一致的根节点,说明存在多颗树,则返回一个空列表;
否则返回构成最小生成树的边的集合。

/**
 * Definition for a Connection.
 * class Connection {
 * public:
 *   string city1, city2;
 *   int cost;
 *   Connection(string& city1, string& city2, int cost) {
 *       this->city1 = city1;
 *       this->city2 = city2;
 *       this->cost = cost;
 * }
 */
 class cmp{
    public:
        bool operator() (const Connection& a, const Connection& b) {
            
            if (a.cost != b.cost) 
                 return a.cost > b.cost;
            
            else if (a.city1 != b.city1)
                return a.city1 > b.city1;
            
            else 
                return a.city2 > b.city2;
        }
 };
 

 
class Solution {
public:
    /**
     * @param connections given a list of connections include two cities and cost
     * @return a list of connections from results
     */
    vector<Connection> lowestCost(vector<Connection>& connections) {
        // Write your code here
        priority_queue<Connection, vector<Connection>, cmp> queue;
        unordered_map<string, string> roots;
        set<string> nodes;
        vector<Connection> res;
        
        for (int i=0; i<connections.size(); i++) {
            string city1 = connections[i].city1;
            string city2 = connections[i].city2;
            
            queue.push(connections[i]);
            roots[city1] = city1;
            roots[city2] = city2;
        }
        
        while(!queue.empty()) {
            Connection tmp = queue.top();
            queue.pop();
            string city1 = tmp.city1, city2 = tmp.city2,
                root1 = findRoot(roots, city1), root2 = findRoot(roots, city2);
            
            if (root1 == root2)
                continue;
                
            if (nodes.find(root1)!=nodes.end())
                roots[root2] = root1;
            else 
                roots[root1] = root2;
                
            nodes.insert(root1); nodes.insert(root2);
            
            res.push_back(tmp);
        }
        
        int count = 0; 
        unordered_map<string, string>::iterator iter = roots.begin();
        
        string tt = findRoot(roots, (*iter).first);
        
        for ( ++iter; iter != roots.end(); iter++ ){
            if (findRoot(roots, (*iter).first) != tt){
                count = -1; 
                break;
            }
        }
        
        if (count == -1) {
            return vector<Connection>();
        } else {
            return res;
        }
        
        
    }
    
     string findRoot(unordered_map<string,string>& roots, string city) {
        while (city != roots[city]) {
            city = roots[city];
        }
        
        return city;
     }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值