3-25 树的最大连通分支问题
给定一棵树 T,树中每个顶点 u 都有一个权 w(u),权可以是负数。现在要找到树 T 的一个连通子图使该子图的权之和最大。
对于给定的树 T,编程计算树 T 的最大连通分支。
数据输入:
第 1 行有 1 个正整数 n,表示树 T 有 n 个顶点。树 T 的顶点编号为 1,…,n。第 2 行有 n 个整数,表示 n 个顶点的权值。接下来的 n-1 行中,每 行有表示树 T 的一条边的 2 个整数 u,v,表示顶点 u 与顶点 v 相连。
Java
import java.util.Scanner;
public class ShuDeZuiDaLianTongFenZhi {
private static class Node{
int s;
Node next;
}
private static int n;
private static int[] w;
private static Node[] child;
private static int[] vis;
private static int maxw;
private static int[] sum;
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int a, b;
while (true){
maxw = 0;
n = input.nextInt();
w = new int[n+1];
child = new Node[n+1];
vis = new int[n+1];
sum = new int[n+1];
for(int i=1; i<=n; i++)
w[i] = input.nextInt();
for(int i=1; i<=n-1; i++){
a = input.nextInt();
b = input.nextInt();
Node p = new Node();
p.s = a;
p.next = child[b];
child[b] = p;
p = new Node();
p.s = b;
p.next = child[a];
child[a] = p;
}
build(1);
comp(1);
for(int i=1; i<=n; i++)
if(sum[i] > maxw)
maxw = sum[i];
System.out.println(maxw);
}
}
private static void build(int k){
Node p;
Node q = new Node();
vis[k] = 1;
p = child[k];
while (p != null){
int i = p.s;
if(vis[i] > 0)
if(p == child[k]){
child[k] = p.next;
p = child[k];
}
else {
q.next = p.next;
p = q.next;
}
else{
build(i);
if(p == child[k])
q = child[k];
else
q = q.next;
p = p.next;
}
}
}
private static void comp(int k){
Node p = child[k];
while (p != null){
int i = p.s;
comp(i);
if(sum[i] > 0)
sum[k] += sum[i];
p = p.next;
}
sum[k] += w[k];
}
}
Input & Output
5
-1 1 3 1 -1
4 1
1 3
1 2
4 5
4
Reference
王晓东《计算机算法设计与分析》(第3版)P99