• + 0 comments

    Here's in JS, with added comments and descriptive variable names to assist.

    function roadsAndLibraries(n, c_lib, c_road, cities) {
        let spent = 0;
        let connects = new Map();
        let visited = new Map();
        const unvisited = [];
        const regions = [];
        
        // Populate connections and build out unvisited stack;
        cities.forEach(city => {
            const cityInd = city[0];
            const dest = city[1];
            
            unvisited.push(cityInd);
            connects.set(cityInd, connects.has(cityInd) ? [...connects.get(cityInd), dest] : [dest]);
            connects.set(dest, connects.has(dest) ? [...connects.get(dest), cityInd] : [cityInd]);
        });
    
        // recursive visitation, returns self and further explores connected unvisited cities
        const visit = (current) => {
            if(!visited.has(current)) {
                visited.set(current, true);
                let currentRegion = [current];
                const neighs = connects.get(current);
                neighs.forEach((n) => {
                   currentRegion = [...currentRegion, ...visit(n)];
                });
                
                return currentRegion;
            }
            
            return [];
        };  
        
        // visits each node, if already visited in a preceeding exploration session, 
        // skip, as already in established region, otherwise begin building out a new region.
        while(unvisited.length > 0) {
            const current = unvisited.pop();
            if(!visited.has(current)) {
                regions.push(visit(current));
            }
        }
        
        // Fill out cost of unconnected cities, i.e. cities which weren't given any neighbours in the input.
        // These all will be solo cities with their own library.
        for(let i = 1; i <= n; i++) {
            if(!connects.has(i)) {
                spent += c_lib;
            }
        }
        
        // Fill out the best case for each region, between one of two options,
        // either every city with their own library, or one library and all cities connected by one road to another.
        regions.forEach(r => {
            const costOfAllLibrary = c_lib * r.length;
            const costOfOneLibraryWithRoads = c_lib + (r.length - 1) * c_road;
            spent += Math.min(costOfAllLibrary, costOfOneLibraryWithRoads);
        });
    
        return spent;
    }