You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

302 lines
9.4 KiB
Java

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*This is a java program to create Prufer code for a tree. In combinatorial mathematics, the Prüfer sequence (also Prüfer code or Prüfer numbers) of a labeled tree is a unique sequence associated with the tree. The sequence for a tree on n vertices has length n 2, and can be generated by a simple iterative algorithm.*/
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import java.util.Set;
public class PruferCode
{
public static List<Integer>[] getRandomTree2(int n, Random rnd)
{
@SuppressWarnings("unchecked")
List<Integer>[] t = new List[n];
for (int i = 0; i < n; i++)
t[i] = new ArrayList<>();
int[] p = new int[n];
for (int i = 0, j; i < n; j = rnd.nextInt(i + 1), p[i] = p[j], p[j] = i, i++)
; // random permutation
for (int i = 1; i < n; i++)
{
int parent = p[rnd.nextInt(i)];
t[parent].add(p[i]);
t[p[i]].add(parent);
}
return t;
}
public static List<Integer>[] pruferCode2Tree(int[] pruferCode)
{
int n = pruferCode.length + 2;
@SuppressWarnings("unchecked")
List<Integer>[] tree = new List[n];
for (int i = 0; i < n; i++)
tree[i] = new ArrayList<>();
int[] degree = new int[n];
Arrays.fill(degree, 1);
for (int v : pruferCode)
++degree[v];
int ptr = 0;
while (degree[ptr] != 1)
++ptr;
int leaf = ptr;
for (int v : pruferCode)
{
tree[leaf].add(v);
tree[v].add(leaf);
--degree[leaf];
--degree[v];
if (degree[v] == 1 && v < ptr)
{
leaf = v;
}
else
{
for (++ptr; ptr < n && degree[ptr] != 1; ++ptr)
;
leaf = ptr;
}
}
for (int v = 0; v < n - 1; v++)
{
if (degree[v] == 1)
{
tree[v].add(n - 1);
tree[n - 1].add(v);
}
}
return tree;
}
public static int[] tree2PruferCode(List<Integer>[] tree)
{
int n = tree.length;
int[] parent = new int[n];
parent[n - 1] = -1;
pruferDfs(tree, parent, n - 1);
int[] degree = new int[n];
int ptr = -1;
for (int i = 0; i < n; ++i)
{
degree[i] = tree[i].size();
if (degree[i] == 1 && ptr == -1)
ptr = i;
}
int[] res = new int[n - 2];
int leaf = ptr;
for (int i = 0; i < n - 2; ++i)
{
int next = parent[leaf];
res[i] = next;
--degree[next];
if (degree[next] == 1 && next < ptr)
{
leaf = next;
}
else
{
++ptr;
while (ptr < n && degree[ptr] != 1)
++ptr;
leaf = ptr;
}
}
return res;
}
static void pruferDfs(List<Integer>[] tree, int[] parent, int v)
{
for (int i = 0; i < tree[v].size(); ++i)
{
int to = tree[v].get(i);
if (to != parent[v])
{
parent[to] = v;
pruferDfs(tree, parent, to);
}
}
}
// precondition: n >= 2
public static List<Integer>[] getRandomTree(int V, Random rnd)
{
int[] a = new int[V - 2];
for (int i = 0; i < a.length; i++)
{
a[i] = rnd.nextInt(V);
}
return pruferCode2Tree(a);
}
// precondition: V >= 2, V-1 <= E <= V*(V-1)/2
public static List<Integer>[] getRandomUndirectedConnectedGraph(int V,
int E, Random rnd)
{
List<Integer>[] g = getRandomTree(V, rnd);
Set<Long> edgeSet = new LinkedHashSet<>();
for (int i = 0; i < V; i++)
{
for (int j = i + 1; j < V; j++)
{
edgeSet.add(((long) i << 32) + j);
}
}
for (int i = 0; i < V; i++)
{
for (int j : g[i])
{
edgeSet.remove(((long) i << 32) + j);
}
}
List<Long> edges = new ArrayList<>(edgeSet);
for (int x : getRandomArrangement(edges.size(), E - (V - 1), rnd))
{
long e = edges.get(x);
int u = (int) (e >>> 32);
int v = (int) e;
g[u].add(v);
g[v].add(u);
}
for (int i = 0; i < V; i++)
Collections.sort(g[i]);
return g;
}
// precondition: V >= 2, V-1 <= E <= V*(V-1)/2
public static List<Integer>[] getRandomUndirectedConnectedGraph2(int V,
int E, Random rnd)
{
List<Integer>[] g = getRandomTree(V, rnd);
Set<Long> edgeSet = new LinkedHashSet<>();
for (int i = 0; i < V; i++)
{
for (int j : g[i])
{
edgeSet.add(((long) i << 32) + j);
}
}
for (int i = 0; i < E - (V - 1); i++)
{
int u;
int v;
long edge;
while (true)
{
u = rnd.nextInt(V);
v = rnd.nextInt(V);
edge = ((long) u << 32) + v;
if (u < v && !edgeSet.contains(edge))
break;
}
edgeSet.add(edge);
g[u].add(v);
g[v].add(u);
}
for (int i = 0; i < V; i++)
Collections.sort(g[i]);
return g;
}
static int[] getRandomArrangement(int n, int m, Random rnd)
{
int[] res = new int[n];
for (int i = 0; i < n; i++)
{
res[i] = i;
}
for (int i = 0; i < m; i++)
{
int j = n - 1 - rnd.nextInt(n - i);
int t = res[i];
res[i] = res[j];
res[j] = t;
}
return Arrays.copyOf(res, m);
}
static void checkGraph(int V, int E, Random rnd)
{
List<Integer>[] g = getRandomUndirectedConnectedGraph(V, E, rnd);
int n = g.length;
int[][] a = new int[n][n];
int edges = 0;
for (int i = 0; i < n; i++)
{
for (int j : g[i])
{
++a[i][j];
++edges;
}
}
if (edges != 2 * E)
{
throw new RuntimeException();
}
for (int i = 0; i < n; i++)
{
if (a[i][i] != 0)
{
throw new RuntimeException();
}
for (int j = 0; j < n; j++)
{
if (a[i][j] != a[j][i] || a[i][j] != 0 && a[i][j] != 1)
{
throw new RuntimeException();
}
}
}
}
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
System.out.println("Enter the length of code: ");
int n = sc.nextInt();
int[] code = new int[n];
for (int i = 0; i < n; i++)
{
code[i] = sc.nextInt();
}
List<Integer>[] tree = pruferCode2Tree(code);
Random rnd = new Random(1);
for (int step = 0; step < 1000; step++)
{
int V = rnd.nextInt(50) + 2;
checkGraph(V, V - 1, rnd);
checkGraph(V, V * (V - 1) / 2, rnd);
checkGraph(V, rnd.nextInt(V * (V - 1) / 2 - (V - 1) + 1) + V - 1,
rnd);
}
System.out.println("Prufer code to tree conversion: "
+ Arrays.toString(tree));
System.out.println("Tree to prufer code conversion: "
+ Arrays.toString(tree2PruferCode(tree)));
sc.close();
}
}
/*
Enter the length of code:
4
2 3 4 3
Prufer code to tree conversion: [[2], [3], [0, 4], [1, 4, 5], [2, 3], [3]]
Tree to prufer code conversion: [2, 3, 4, 3]
Enter the length of code:
3
2 4 3
Prufer code to tree conversion: [[2], [4], [0, 3], [2, 4], [1, 3]]
Tree to prufer code conversion: [2, 4, 3]
Enter the length of code:
5
3 4 5 1 6
Prufer code to tree conversion: [[3], [4, 6], [4], [0, 5], [2, 1], [3, 6], [1, 5]]
Tree to prufer code conversion: [3, 4, 5, 1, 6]