Roads and Libraries

Sort by

recency

|

15 Discussions

|

  • + 0 comments

    Kotlin solution

    fun roadsAndLibraries(
        n: Int,
        c_lib: Int,
        c_road: Int,
        cities: Array<Array<Int>>
    ): Long {
        if (c_lib<=c_road) return (c_lib.toLong()*n)
        val nodes = (1..n).map {Node(it)}
        for (edge in cities) {
            connectNodes(nodes[edge[0]-1], nodes[edge[1]-1])
        }
        val groups = mutableSetOf<Set<Node>>()
        val visited = mutableSetOf<Node>()
        for (i in nodes.indices) {
            if (visited.contains(nodes[i])) continue
            val reachable = findReachable(nodes[i])
            groups.add(reachable)
            visited.addAll(reachable)
        }
        val costOfLib = c_lib*groups.size.toLong()
        val costOfRoads = c_road*groups.map {it.size.toLong() - 1}
                                .sum()
        
        return costOfLib + costOfRoads
    }
    
    class Node(val num: Int) {
        val connections = mutableSetOf<Node>()
    }
    
    fun findReachable(node:Node): Set<Node> {
        val visited = mutableSetOf<Node>()
        val queue: Queue<Node> = LinkedList()
        queue.add(node)
        while (!queue.isEmpty()) {
            val next = queue.remove()
            if (!visited.contains(next)) {
                visited.add(next)
                for (n in next.connections) {
                    if (!visited.contains(n)) {
                        queue.add(n)
                    }
                }
            }
        }
        return visited
    }
    
    fun connectNodes(a:Node, b:Node) {
        a.connections.add(b)
        b.connections.add(a)
    }
    
  • + 0 comments

    A very easy implementation using DFS and "Divide and Conquer Approach"

    !/bin/python3
    
    import math
    import os
    import random
    import re
    import sys
    
    #
    # Complete the 'roadsAndLibraries' function below.
    #
    # The function is expected to return a LONG_INTEGER.
    # The function accepts following parameters:
    #  1. INTEGER n
    #  2. INTEGER c_lib
    #  3. INTEGER c_road
    #  4. 2D_INTEGER_ARRAY cities
    #
    
    #Here we use the "Divide and Conquer" approach 
    #to solve the subproblem for each disconnected component
    def roadsAndLibraries(n, c_lib, c_road, cities):
        # Write your code here
        
        #To store the graph
        adjacency_list=[[]for i in range(n+1)]
        
        #Fill in the adjacency list
        for x,y in cities:
            adjacency_list[x].append(y)
            adjacency_list[y].append(x)
        
        #The cost reqd
        total_cost=0
        
        #Tells if a city has been visited or not
        visited=[False for i in range(n+1)]
        
        #Depth First Search
        def dfs(u,adjacency_list,visited):
            visited[u]=True
            
            #Number of visited till now
            n_cities=1
            for v in adjacency_list[u]:
                if(visited[v]==False):
                    n_cities+=dfs(v,adjacency_list,visited)
            
            return n_cities
        
        for u in range(1,n+1):
            if(visited[u]==False):
                
                #Place a library in city 'v' and bulid the roads to the remaining cities
                #excluding cylces(min spanning tree due to equal weight edges) 
                
                n_cities=dfs(u,adjacency_list,visited)
                cost1=((n_cities-1)*(c_road))+c_lib
                
                #In case , placing library at each city is beneficial
                cost2=n_cities*c_lib
                
                #Considering each disconnected component and summing up the costs 
                total_cost+=min(cost1,cost2)
        return total_cost
                
    if __name__ == '__main__':
        fptr = open(os.environ['OUTPUT_PATH'], 'w')
    
        q = int(input().strip())
    
        for q_itr in range(q):
            first_multiple_input = input().rstrip().split()
    
            n = int(first_multiple_input[0])
    
            m = int(first_multiple_input[1])
    
            c_lib = int(first_multiple_input[2])
    
            c_road = int(first_multiple_input[3])
    
            cities = []
    
            for _ in range(m):
                cities.append(list(map(int, input().rstrip().split())))
    
            result = roadsAndLibraries(n, c_lib, c_road, cities)
    
            fptr.write(str(result) + '\n')
    
        fptr.close()
    
  • + 0 comments
    def roadsAndLibraries(n, c_lib, c_road, cities):
        # If library cost is less than or equal to road cost, build a library in each city
        if c_lib <= c_road:
            return c_lib * n
        
        # Initialize disjoint set (union-find) structures
        root = list(range(n + 1))
        rank = [0] * (n + 1)
        
        def find_root(i):
            if root[i] != i:
                root[i] = find_root(root[i])  # Path compression
            return root[i]
        
        def union(a, b):
            i, j = find_root(a), find_root(b)
            if i != j:
                # Union by rank
                if rank[i] > rank[j]:
                    root[j] = i
                elif rank[i] < rank[j]:
                    root[i] = j
                else:
                    root[j] = i
                    rank[i] += 1
        
        # Union all connected cities
        for a, b in cities:
            union(a, b)
        
        # Count connected components
        k = sum(1 for city in range(1, n + 1) if root[city] == city)
        
        # Calculate total cost: one library per component + roads for remaining cities
        return c_lib * k + c_road * (n - k)
    
  • + 0 comments

    Java O(n+m)

     public static long roadsAndLibraries(int n, int c_lib, int c_road, List<List<Integer>> cities) {
                if (c_lib <= c_road) {
                    return (long) n * c_lib;
                }
    
                List<List<Integer>> adjList = new ArrayList<>();
                for (int i = 0; i <= n; i++) {
                    adjList.add(new ArrayList<>());
                }
    
                for (List<Integer> city : cities) {
                    int u = city.get(0);
                    int v = city.get(1);
                    adjList.get(u).add(v);
                    adjList.get(v).add(u);
                }
    
                boolean[] visited = new boolean[n + 1];
                long totalCost = 0;
    
                for (int i = 1; i <= n; i++) {
                    if (!visited[i]) {
                        long componentSize = dfs(i, adjList, visited);
                        totalCost += c_lib + (componentSize - 1) * c_road;
                    }
                }
    
                return totalCost;
            }
    
            private static long dfs(int node, List<List<Integer>> adjList, boolean[] visited) {
                Stack<Integer> stack = new Stack<>();
                stack.push(node);
                visited[node] = true;
                long size = 0;
    
                while (!stack.isEmpty()) {
                    int current = stack.pop();
                    size++;
                    for (int neighbor : adjList.get(current)) {
                        if (!visited[neighbor]) {
                            visited[neighbor] = true;
                            stack.push(neighbor);
                        }
                    }
                }
    
                return size;
            }
    
  • + 0 comments

    JavaScript

    function roadsAndLibraries(n, c_lib, c_road, cities) {
        // Write your code here
        if (c_road >= c_lib) return n * c_lib
        
        let arr = []
        for (let i = 1; i <= n; i++) arr[i] = [i]
        for (let i = 0; i < cities.length; i++) {
            let [m, n] = cities[i]
            if (arr[m] === arr[n]) continue
            if (arr[m].length < arr[n].length) [m, n] = [n, m]
            for (let temp of arr[n]) arr[m].push(temp), arr[temp] = arr[m]
        }
        let groups = new Set()
        for (let temp of arr.slice(1)) groups.add(temp)
        let cost = groups.size * c_lib + Array.from(groups).map(group => group.length - 1).reduce((acc, cur) => acc + cur * c_road, 0)
        return cost
    }