Given a tree, assign weights to each edge in order to minimize the weight of every path (u, v) in the tree

LavaMaster :

Given a tree, assign weights to each edge in order to minimize the weight of every path (u, v) in the tree. To clarify, we are minimizing the maximum weight on every path in the tree

Can this question be solved with some sort of data structure or algorithm? How do you determine which weights to place on each edge in the tree? The input is a number N, and you have to place weights in between the values of [0, N-2] (inclusive) on each edge of the tree.

Let me clarify the question. Let's say you have an edge (1, 2) and you place weight 3 on that edge. The actual definition of "weight" in the context of the question is the minimum-most value from [0, N-2] that IS NOT present on the path from (u, v). Even though the weight on the specific edge is three, the actual weight in the context of the question is zero. Also, the root of the tree in this question is 1.

My original approach for this question was to add the values from [0, N-2] (the edge values we can assign to each edge) to a stack, then traverse the tree using DFS and pop a value from the stack (the maximum-most edge value) and assign it to the edge. This, however, does not minimize the cost over all paths. Keep in mind, the cost is the minimum-most value not present on the path from (u, v). We are trying to place the costs to minimize the costs on every possible path.

My code:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Stack;
import java.util.Iterator;
import java.util.ArrayList;
    public class Mex    {
        public static void main (String [] args) throws IOException {
            BufferedReader b1 = new BufferedReader(new InputStreamReader(System.in));
            int n = Integer.parseInt(b1.readLine());
            LinkedList<Integer>[] adj = new LinkedList[n+1];
            ArrayList<Integer> v = new ArrayList<Integer>(n+1);
            for(int i = 1; i<=n; i++) {
                adj[i] = new LinkedList<Integer>();
            }
            for(int i = 0; i<n-1; i++) {
                String [] edge = (b1.readLine()).split(" ");
                adj[Integer.parseInt(edge[0])].add(Integer.parseInt(edge[1]));
                adj[Integer.parseInt(edge[1])].add(Integer.parseInt(edge[0]));
                v.add(Integer.parseInt(edge[0]));
                v.add(Integer.parseInt(edge[1]));
            }
            dfs(adj, 1, n, v);


        }
        static void dfs(LinkedList<Integer> adj[], int u, int n, ArrayList<Integer> order)   { 
            Stack<Integer> values = new Stack<>();
            int [][] weight = new int[n+1][n+1];
            for(int i = 0; i<n-1; i++) {
                values.push(i);
            }
            boolean [] visited = new boolean[n+1];
            int [] parent = new int[n+1];
            for (int i = 1; i < n+1; i++) 
                visited[i] = false; 

            Stack<Integer> stack = new Stack<>(); 

            stack.push(u); 

            while(stack.empty() == false) { 
                u = stack.peek(); 
                stack.pop(); 

                if(visited[u] == false)  { 
                  visited[u]  = true; 
                  if(u!= 1) {
                    if(adj[u].size()==1) {
                        if(values.contains(0)) {
                            weight[parent[u]][u] = 0;
                            values.remove(0);
                        }
                        else {
                            int w = values.pop();
                            weight[parent[u]][u] = w;
                        }
                    }
                    else {
                        int w = values.pop();
                        weight[parent[u]][u] = w;   
                    }
                  }
                } 

                Iterator<Integer> itr = adj[u].iterator(); 

                while (itr.hasNext())  {                    
                    int v = itr.next(); 
                    if(parent[v]==0 && v!=1) {
                        parent[v] = u;
                    }
                    if(!visited[v]) 
                        stack.push(v); 
                } 

            } 
            for(int i = 0; i<order.size()-1; i+=2) {
                if(parent[order.get(i)]==order.get(i+1)) {
                    System.out.println(weight[order.get(i+1)][order.get(i)]);               
                }
                else {
                    System.out.println(weight[order.get(i)][order.get(i+1)]);               
                }
            }
        } 
    }
Ekesh Kumar :

There's no special algorithm or data structure that you need to solve this problem. There is just one key observation you need to make:

  • If every vertex in your graph has degree 2 or less, then no matter how you place the vertices, there's always a path that touches every edge. Therefore, it doesn't matter how you place the labels.

  • If there's at least one vertex in your graph with degree 3 or more, then we can place 0, 1, and 2 on each side of this vertex. Now, the maximum minimum excludant is 2 since we can take a path from 0 to 1. It's pretty clear that you can't do better than this since you can always start at 0 and go to 1 to get a minimum excludant of 2. Therefore, you can make the edges 0, 1, and 2 incident to the same vertex. The other labels don't matter.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=293025&siteId=1