import java.util.*; import java.io.*; public class Main{ int[] value; //记录每个节点的值 int[][] rec; //记录每个节点上不同情况下的最大值 int ans=0; //记录和 int[][] child; //记录每个节点的所有子节点 private void dfs1(int index) { rec[index][0]=value[index]; //赋初始值,0项记录该节点最开始的值 int lens=child[index].length; //计算该节点有几个子节点 for(int i=0;i<lens;i++) { //依次遍历子节点 int c=child[index][i]; dfs1(c); //普通递归,逐级向下 rec[index][0]=Math.max(rec[index][0], rec[c][0]); //比较子节点和父节点的值的大小,最大值记录到父节点0项中 if(rec[c][0]>rec[index][1]) { //次大值记录到父节点1项中 rec[index][2]=rec[index][1]; rec[index][1]=rec[c][0]; }else if(rec[c][0]>rec[index][2]) { //再次大值记录到父节点2项中 rec[index][2]=rec[c][0]; } } } private void dfs2(int index,int maxOut) { //传入起始节点和该节点对应的其他节点最大的value(maxOut) ans+=Math.abs(rec[index][0]-maxOut); //对每一个节点,都用他0项中记录的最大value减去maxOut,求绝对值,加到和里 maxOut=Math.max(maxOut,value[index]); int lens=child[index].length; for(int i=0;i<lens;i++){ int c=child[index][i]; //遍历子节点 if(rec[c][0]==rec[index][1]) dfs2(c,Math.max(maxOut,rec[index][2])); //如果c是次大值节点,用再次大值节点的值操作 else dfs2(c,Math.max(maxOut,rec[index][1])); } } private int[] add(int[] child,int index) { //因为不知道java用数组套动态数组的方法,所以只能给静态数组手动扩容 int[] child2=new int[child.length+1]; System.arraycopy(child, 0, child2, 0, child.length); child2[child2.length-1]=index; return child2; } public void init() throws IOException { StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); in.nextToken(); int n=(int) in.nval; //简单读取 child=new int[n][0]; value=new int[n]; rec=new int[n][3]; for(int i=1;i<n;i++){ in.nextToken(); int k=(int) in.nval; //找到i的父亲k child[k]=add(child[k],i); //把i加到child[k]数组里,双层的,注意点 } for(int i=0;i<n;i++){ in.nextToken(); value[i]=(int) in.nval; } dfs1(0); //记录每个节点的几个最大值 dfs2(0,0); //求和 } public static void main(String[] args) throws IOException{ Main m=new Main(); m.init(); System.out.println(m.ans-m.rec[0][0]); //排除根节点 } }