DEV Community

Prashant Mishra
Prashant Mishra

Posted on

3108. Minimum Cost Walk in Weighted Graph

Problem

TC: O(n*4alpha)

class Solution {
    public int[] minimumCost(int n, int[][] edges, int[][] query) {
        Disjoint d = new Disjoint(n);
        Map<Integer,Integer> map = new HashMap<>();
        for(int edge[]  :edges){
            int u = edge[0];
            int v = edge[1];
            int w = edge[2];
            //if parents are not same then union them (will create  common parent for both u and v)
            if(d.findParent(u) != d.findParent(v)){
                //since u and v will be unioned there values will also be updated as below
                //distance value of the first part/component
                int diU = map.getOrDefault(d.findParent(u),w);
                //distance value of the second part/component
                int diV = map.getOrDefault(d.findParent(v),w);
                //union u and v componts
                d.union(u,v);
                int p  = d.findParent(u); //get parent of u or v does not matter their parents would be same after their union
                map.put(p, diU & diV & w); // update the common distance at the parent level ( both the components will be come one unified component and they will have a common smaller distance created by &)
            }
            else{
                // if they have same common parent then we just have to updated the distance by & w at the parent node
                int p = d.findParent(u);
                map.put(p, map.get(p) & w);
            }
        }
        int result[] = new int[query.length];
        for(int i =0;i<query.length;i++){
            int u = query[i][0];
            int v = query[i][1];
            // only if the parent are same is when there is an edge between the nodes(direct edge or indirect edge)
            //and the parent node will have the the lowest values by & (computed in the above part)
            if(d.findParent(u) == d.findParent(v)){
                result[i] = map.get(d.findParent(u));
            }
            else result[i] = -1;// otherwise there is no direct/indirect edge between u and v
        }
        return result;
    }
}
class Disjoint{
    List<Integer> parent = new ArrayList<>();
    List<Integer> rank = new ArrayList<>();
    public Disjoint(int n){
        for(int  i = 0;i< n;i++){
            parent.add(i);
            rank.add(1);
        }
    }
    public int findParent(int n){
        if(n == parent.get(n)) return n;
        else{
            parent.set(n, findParent(parent.get(n)));
            return parent.get(n);
        }
    }
    public void union(int u, int v){
        u = findParent(u);
        v = findParent(v);
        if(u!=v){
            if(rank.get(u) > rank.get(v)){
                parent.set(v,u);
            }
            else if(rank.get(u) < rank.get(v)){
                parent.set(u,v);
            }
            else{
                parent.set(v,u);
                rank.set(u, rank.get(v) + rank.get(u));
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

More readable way( same approach though)

class Solution {
    public int[] minimumCost(int n, int[][] edges, int[][] query) {
        Disjoint d = new Disjoint(n);
        Map<Integer,Integer> map = new HashMap<>();
        // do the union of all the nodes to form all the components
        for(int edge[]  :edges){
            int u = edge[0];
            int v = edge[1];
            int w = edge[2];
            if(d.findParent(u) != d.findParent(v)){
                d.union(u,v);
            }
        }
        //iterate over the edges to update the min cost
        for(int edge[]  :edges){
            int u = edge[0];
            int v = edge[1];
            int w = edge[2];
            int parent  = d.findParent(u);// parent of u and v are same ( as they have already been unified in the above iteration)
            if(!map.containsKey(parent)){
                map.put(parent,w);
            }
            else map.put(parent, map.get(parent) & w);// if the parent is alredy present just & the current weight
        }

        int result[] = new int[query.length];
        for(int i =0;i<query.length;i++){
            int u = query[i][0];
            int v = query[i][1];
            // only if the parent are same is when there is an edge between the nodes(direct edge or indirect edge)
            //and the parent node will have the the lowest values by & (computed in the above part)
            if(d.findParent(u) == d.findParent(v)){
                result[i] = map.get(d.findParent(u));
            }
            else result[i] = -1;// otherwise there is no direct/indirect edge between u and v
        }
        return result;
    }
}
class Disjoint{
    List<Integer> parent = new ArrayList<>();
    List<Integer> rank = new ArrayList<>();
    public Disjoint(int n){
        for(int  i = 0;i< n;i++){
            parent.add(i);
            rank.add(1);
        }
    }
    public int findParent(int n){
        if(n == parent.get(n)) return n;
        else{
            parent.set(n, findParent(parent.get(n)));
            return parent.get(n);
        }
    }
    public void union(int u, int v){
        u = findParent(u);
        v = findParent(v);
        if(u!=v){
            if(rank.get(u) > rank.get(v)){
                parent.set(v,u);
            }
            else if(rank.get(u) < rank.get(v)){
                parent.set(u,v);
            }
            else{
                parent.set(v,u);
                rank.set(u, rank.get(v) + rank.get(u));
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

DFS approach:

class Solution {
    int minCost[] = new int[1]; // to keep track of cost for each component
    public int[] minimumCost(int n, int[][] edges, int[][] query) {
        Map<Integer,List<Pair>> adj = new HashMap<>();
        for(int i =0;i< n;i++){
            adj.put(i, new ArrayList<>());
        }
        for(int edge[] : edges){
            int u = edge[0];
            int v = edge[1];
            int w = edge[2];
            List<Pair> list = adj.getOrDefault(u, new ArrayList<>());
            list.add(new Pair(v,w));
            adj.put(u, list);
            List<Pair> list2 = adj.getOrDefault(v, new ArrayList<>());
            list2.add(new Pair(u,w));
            adj.put(v, list2);
        }
        int visited[] = new int[n]; // along with keep track of what node is visited it will also tell us component to which the node belogs
        Map<Integer,Integer> componentCost = new HashMap<>();
        int currentComponent  =1;
        for(int i=0;i< n;i++){
            if(visited[i] ==0){
                minCost[0] = Integer.MAX_VALUE; // to make sure all the binary value are 1 so that it does not affect the actual & results we will get in the dfs from the edges of this compnent
                dfs(i,adj,visited,currentComponent);
                componentCost.put(currentComponent, minCost[0]);
                currentComponent+=1; // after this we will try to traverse the next component if present
            }
        }
        int result[] = new int[query.length];
        for(int i =0;i< query.length;i++){
            int u  = query[i][0];
            int v = query[i][1];
            // if u and v  are part of the same component
            if(visited[u] == visited[v]){
                result[i]  = componentCost.get(visited[u]);
            }
            else result[i] = -1;
        }
        return result;
    }
    public void dfs(int node, Map<Integer,List<Pair>> adj,int [] visited, int currentComponent){
        visited[node] = currentComponent; //insted of putting 1 we will put the component no. of this node, this will help us greatly in the query part
        for(Pair p : adj.get(node)){
            int adjNode = p.n;
            minCost[0]&=p.w;// even if it is already visited node then also we want to & all the the weights to get the min cost for the current component
            if(visited[adjNode]==0){
                dfs(adjNode, adj, visited,currentComponent);
            }
        }
    }
}
class Pair{
    int n;
    int w;
    public Pair(int n ,int w){
        this.n = n;
        this.w = w;
    }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)