There are N
cities numbered from 1 to N
.
You are given connections
, where each connections[i] = [city1, city2, cost]
represents the cost to connect city1
and city2
together. (A connection is bidirectional: connecting city1
and city2
is the same as connecting city2
and city1
.)
Return the minimum cost so that for every pair of cities, there exists a path of connections (possibly of length 1) that connects those two cities together. The cost is the sum of the connection costs used. If the task is impossible, return -1.
Example 1:
Input: N = 3, connections = [[1,2,5],[1,3,6],[2,3,1]]
Output: 6
Explanation:
Choosing any 2 edges will connect all cities so we choose the minimum 2.
思路:可以用dijkstra来做,记住,建立图的时候,不能用hashmap<Integer, HashMap<Integer, Integer>> ,一定要用HashMap<Integer, List<Node>>来建立图,因为如果node与node之间有两条以上的path,hashmap会覆盖值,所以用list<Node>来包含所有边的情况;
class Solution {
private class Node {
public int city;
public int cost;
public Node(int city, int cost) {
this.city = city;
this.cost = cost;
}
}
private class NodeComparator implements Comparator<Node> {
@Override
public int compare(Node a, Node b) {
return a.cost - b.cost;
}
}
public int minimumCost(int N, int[][] connections) {
if(connections == null || connections.length == 0 ||
connections[0].length == 0) {
return -1;
}
// build graph;
// fromCity List of (Node<toCity,cost>)
HashMap<Integer, List<Node>> graph = new HashMap<>();
for(int i = 1; i <= N; i++) {
graph.putIfAbsent(i, new ArrayList<Node>());
}
for(int i = 0; i < connections.length; i++) {
int fromcity = connections[i][0];
int tocity = connections[i][1];
int cost = connections[i][2];
graph.get(fromcity).add(new Node(tocity, cost));
graph.get(tocity).add(new Node(fromcity, cost));
}
HashSet<Integer> visited = new HashSet<Integer>();
PriorityQueue<Node> pq = new PriorityQueue<Node>(N, new NodeComparator());
pq.offer(new Node(1, 0));
int count = 0;
int totalcost = 0;
while(!pq.isEmpty()) {
Node head = pq.poll();
int cost = head.cost;
int city = head.city;
if(visited.contains(city)) {
continue;
}
visited.add(city);
totalcost += cost;
count++;
for(Node neighbor: graph.get(city)) {
if(!visited.contains(neighbor.city)) {
pq.offer(neighbor);
}
}
}
return count == N ? totalcost : -1;
}
}
Minimum spanning Tree;可以sort每条边,然后每次用最小的边connect,用union find做
class Solution {
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(j != x) {
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;
count--;
}
}
public int getCount() {
return this.count;
}
}
private class connect {
public int from;
public int to;
public int cost;
public connect(int from, int to, int cost) {
this.from = from;
this.to = to;
this.cost = cost;
}
}
private class connectComparator implements Comparator<connect> {
@Override
public int compare(connect a, connect b) {
return a.cost - b.cost;
}
}
public int minimumCost(int N, int[][] connections) {
if(connections == null || connections.length == 0 || connections[0].length == 0) {
return -1;
}
PriorityQueue<connect> pq = new PriorityQueue(N, new connectComparator());
for(int[] e : connections) {
pq.add(new connect(e[0], e[1], e[2]));
}
UnionFind uf = new UnionFind(N);
int totalcost = 0;
while(!pq.isEmpty()) {
connect con = pq.poll();
int a = con.from;
int b = con.to;
if(uf.find(a) != uf.find(b)) {
uf.union(a, b);
totalcost += con.cost;
}
}
if(uf.getCount() == 1) {
return totalcost;
}
return -1;
}
}