Minimum Spanning Tree

Given a list of Connections, which is the Connection class (the city name at both ends of the edge and a cost between them), find edges that can connect all the cities and spend the least amount.
Return the connects if can connect all the cities, otherwise return empty list.

Example

Example 1:

Input:
["Acity","Bcity",1]
["Acity","Ccity",2]
["Bcity","Ccity",3]
Output:
["Acity","Bcity",1]
["Acity","Ccity",2]

Example 2:

Input:
["Acity","Bcity",2]
["Bcity","Dcity",5]
["Acity","Dcity",4]
["Ccity","Ecity",1]
Output:
[]

Explanation:
No way

Notice

Return the connections sorted by the cost, or sorted city1 name if their cost is same, or sorted city2 if their city1 name is also same.

思路:// return empty list好做,判断union find之后的边,是否是n-1
        // 如何用最小的边去连接,方法就是:首先对connect按照value和city进行排序
        // 然后把最小边的node,也就是对应的number取出来,判断是否相连,不相连,连起来,这样一定是先用最小的边把整个图连接起来,
        // 如果全部连起来了,那么后面进来的connection会因为前面已经连起来了,那么不会再连了,因为后面的都是边值比较大的点;所以所求就是最小的cost;

/**
 * Definition for a Connection.
 * public class Connection {
 *   public String city1, city2;
 *   public int cost;
 *   public Connection(String city1, String city2, int cost) {
 *       this.city1 = city1;
 *       this.city2 = city2;
 *       this.cost = cost;
 *   }
 * }
 */
public class Solution {
    /**
     * @param connections given a list of connections include two cities and cost
     * @return a list of connections from results
     */
private class UnionFind {
        private int[] father;
        private int count;
        public UnionFind(int n) {
            this.father = new int[n + 1];
            for(int i = 0; i <= n; i++) {
                father[i] = i;
            }
            this.count = n;
        }

        public int find(int x) {
            int j = x;
            while(father[j] != j) {
                j = father[j];
            }
            // path compression;
            while(x != j) {
                int fx = father[x];
                father[x] = j;
                x = fx;
            }
            return j;
        }

        public void union(int a, int b) {
            int root_a = find(a);
            int root_b = find(b);
            if(root_a != root_b) {
                father[root_a] = root_b;
                this.count--;
            }
        }

        public int getCount() {
            return this.count;
        }
    }

    private class ConnectionComparator implements Comparator<Connection> {
        @Override
        public int compare(Connection a, Connection b) {
            if(a.cost != b.cost) {
                return a.cost - b.cost;
            } else {
                if(!a.city1.equals(b.city1)) {
                    return a.city1.compareTo(b.city1);
                } else {
                    return a.city2.compareTo(b.city2);
                }
            }
        }
    }

    public List<Connection> lowestCost(List<Connection> connections) {
        Collections.sort(connections, new ConnectionComparator());
        HashMap<String, Integer> cityMap = new HashMap<>();
        int count = 0;
        for(Connection connection: connections) {
            String city1 = connection.city1;
            if(!cityMap.containsKey(city1)) {
                cityMap.put(city1, count++);
            }
            String city2 = connection.city2;
            if(!cityMap.containsKey(city2)) {
                cityMap.put(city2, count++);
            }
        }
        UnionFind uf = new UnionFind(count);
        List<Connection> list = new ArrayList<>();
        for(Connection connection: connections) {
            int a = cityMap.get(connection.city1);
            int b = cityMap.get(connection.city2);
            if(uf.find(a) != uf.find(b)) {
                uf.union(a, b);
                list.add(connection);
            }
        }
        return uf.getCount() == 1 ? list : new ArrayList<>();
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值