programming-examples/java/Data_Structures/TreeCenters.java

80 lines
2.0 KiB
Java
Raw Normal View History

2019-11-15 12:59:38 +01:00
import java.util.*;
import java.util.stream.Stream;
public class TreeCenters {
// returns 1 or 2 tree centers
// http://en.wikipedia.org/wiki/Graph_center
public static List<Integer> findTreeCenters(List<Integer>[] tree) {
int n = tree.length;
List<Integer> leaves = new ArrayList<>();
int[] degree = new int[n];
for (int i = 0; i < n; i++) {
degree[i] = tree[i].size();
if (degree[i] <= 1) {
leaves.add(i);
}
}
int removedLeaves = leaves.size();
while (removedLeaves < n) {
List<Integer> nleaves = new ArrayList<>();
for (int u : leaves) {
for (int v : tree[u]) {
if (--degree[v] == 1) {
nleaves.add(v);
}
}
}
leaves = nleaves;
removedLeaves += leaves.size();
}
return leaves;
}
// returns vertex that has all its subtrees sizes <= n/2
public static int findTreeCentroid(List<Integer>[] tree, int u, int p) {
int n = tree.length;
int cnt = 1;
boolean goodCenter = true;
for (int v : tree[u]) {
if (v == p) continue;
int res = findTreeCentroid(tree, v, u);
if (res >= 0)
return res;
int size = -res;
goodCenter &= size <= n / 2;
cnt += size;
}
goodCenter &= n - cnt <= n / 2;
return goodCenter ? u : -cnt;
}
public static int diameter(List<Integer>[] tree) {
int furthestVertex = (int) dfs(tree, 0, -1, 0);
return (int) (dfs(tree, furthestVertex, -1, 0) >>> 32);
}
static long dfs(List<Integer>[] tree, int u, int p, int depth) {
long res = ((long) depth << 32) + u;
for (int v : tree[u])
if (v != p)
res = Math.max(res, dfs(tree, v, u, depth + 1));
return res;
}
// Usage example
public static void main(String[] args) {
int n = 4;
List<Integer>[] tree = Stream.generate(ArrayList::new).limit(n).toArray(List[]::new);
tree[3].add(0);
tree[0].add(3);
tree[3].add(1);
tree[1].add(3);
tree[3].add(2);
tree[2].add(3);
System.out.println(3 == findTreeCentroid(tree, 0, -1));
System.out.println(3 == findTreeCenters(tree).get(0));
System.out.println(2 == diameter(tree));
}
}