我想解决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;
}
}
答案 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;