DFS未正确执行

时间:2014-07-16 16:48:13

标签: java algorithm depth-first-search tree-traversal

我想解决this problem,但我仍然遇到问题的一小部分问题。很快,给定一棵树,这棵树的每个顶点都有一些重量。我们将树的总和定义为树中包含的所有节点的所有权重的总和。

我有N个节点,我想计算以这N个节点中每个节点为根的子树的总和。这个总和我想存储在一个数组res[]中。为此,我必须执行DFS并总结正确节点的权重。但是,我的DFS不能像这样工作,我不知道如何纠正它。

编辑:我调试了我的代码,但我不知道如何纠正它。它无法计算叶子的res[]值(对于它们,它不返回任何东西)。此外,它不会计算内部节点的正确值。我认为我必须在int tempRes方法中定义新变量dfs并返回此变量,但在某些时候我必须将其归零,我不知道在哪里。

package searching;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

public class CutTheTree {

    static List<ArrayList<Integer>> adj; //list which stores adjacency nodes, i.e. at position i I have list of the neighbours of node i
    static int N; //number of nodes
    static int[] res; //store the sum of weights of tree rooted at node i
    static boolean[] visited; //array which indicates if I have visited node or not
    static int[] weights;   //array of the given weights of each node
    static int W;   //this variable is not relevant to my problem

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line1 = br.readLine();
        N = Integer.parseInt(line1);
        String[] line2 = br.readLine().split(" ");
        weights = new int[N];       //weights of each vertex
        visited = new boolean[N];
        res = new int[N];
        adj = new ArrayList<ArrayList<Integer>>(N);
        for (int i = 0; i < N; i++) {
            adj.add(i, new ArrayList<Integer>());
        }
        for (int i = 0; i < line2.length; i++) {
            weights[i] = Integer.parseInt(line2[i]);
        }
        W = 0; //total sum
        for (int i = 0; i < weights.length; i++) {
            W+= weights[i];         //total sum of all weights
        }
        for (int i = 0; i < N-1; i++) { //follow N-1 lines of the edges given as pairs, i.e. (1, 3) means edge from vertex 1 to vertex 3
            String[] line3 = br.readLine().split(" ");
            int start = Integer.parseInt(line3[0]);
            int end = Integer.parseInt(line3[1]);
            adj.get(start-1).add(end);      //store adjacent nodes in a linked list; substract 1 from the vtx id, since the indexing starts from 0
            adj.get(end-1).add(start);      //example: vtx 1 is a neighbor of vtx 3 and vtx 3 is neigbor of vtx 1
        }
        dfs(1);     //take vtx one as a root
        for (int i = 0; i < N; i++) {
            System.out.print(res[i] + " ");
        }

    }

    // The problematic function!!!
    private static int dfs(int root) {
        int temp;
        Stack<Integer> st = new Stack<Integer>();
        ArrayList<Integer> neigh = new ArrayList<Integer>(); //list of unvisited neighoring vetrices of the current node
        st.push(root);
        visited[root-1] = true; //mark current node as visited
        while(!st.isEmpty()){
            int curr = st.pop();
            if(isLeaf(curr)){
                res[curr-1]= weights[curr-1];
                return weights[curr-1];
            }
            else{
                neigh = neighbours(curr);
                if(neigh.size() == 0){
                    temp = weights[curr-1]; //if there is no unvisited nodes, return the weight function of the given node; however this does not work for the leaf nodes!                  
                }
                else{ //else I have to visit unvisited neighbors
                    res[curr-1] = weights[curr-1]; //the current res increases by the weight of the given node
                    for (int i = 0; i < neigh.size(); i++) {
                        int child = neigh.get(i);
                        visited[child-1] = true;
                        st.push(child);
                        res[curr-1]+= dfs(child); // for each unvisited neighbor I perform dfs and add the result to the corresponding index of res array
                    }
                }
            }
        }
        return 0;
     //returns ArrayList of unvisited nodes of the current node
    private static ArrayList<Integer> neighbours(int node){
        ArrayList<Integer> res = new ArrayList<Integer>();
        for (int i = 0; i < adj.get(node-1).size(); i++) {
            int child = adj.get(node-1).get(i);
            if(!visited[child-1]){
                res.add(child);
            }
        }
        return res;
    }
}

1 个答案:

答案 0 :(得分:2)

除了叶节点外,dfs方法返回0。

此外,您似乎将递归和迭代方法混合在一起。如果您使用自己的未访问节点堆栈,则不需要依赖递归提供的调用堆栈。

基本上,您需要访问每个节点。在每次访问中,您将节点的权重添加到一个总和,然后将其子项添加到堆栈中。

int result = 0;

while(!st.isEmpty()){
    int curr = st.pop();
    neigh = neighbours(curr);
    result += weights[curr-1]; 
    if(neigh.size() != 0){
        for (int i = 0; i < neigh.size(); i++) {
            int child = neigh.get(i);
            visited[child-1] = true;
            st.push(child);
        }
    }
}

return result;