给定整数N ,任务是生成具有(N – 1)个边的N个节点的随机标记树,而不会形成循环。
注意:下面生成的输出是随机的,可能与代码生成的输出不匹配。
例子:
Input: N = 3
Output:
1 3
1 2
Input: N = 5
Output:
3 2
4 3
1 4
1 5
这种方法使用Prüfer序列生成随机树。
什么是Prüfer序列?
在组合数学中,标记树的Prüfer序列(也称为Prüfer码或Prüfer编号)是与树相关的唯一序列。一棵树在n个顶点上的序列长度为n – 2,可以通过简单的迭代算法生成。
如果节点数为N,则Prüfer序列的长度为(N – 2),每个位置可以有N个可能的值。因此,带有N个节点的可能标记树的数量为N (N – 2) 。
如何使用Prüfer序列生成随机树?
通常,通过以下步骤完成具有N个节点的随机树生成:
- 产生随机序列
S = {s1, s2, s3.....sn-2}
- 其中序列的I∈的每个元素{1,2,3,… N},其中元件的重复被允许
- 从生成的Prüfer序列S生成树:
- 创建具有值{1、2、3,… N}的N个节点
- 求出最小元素X,使得X∈{1,2,3,…N}和X∉S
- 将值为X的节点加入到值为s 1的节点
- 从S删除s 1
- 重复步骤2的相同过程,直到Prüfer序列为空。
例如:
- 节点数= 3
- 然后,Prüfer序列的长度为(N – 2) ,在这种情况下,其长度为1,可能的值可以为{1、2、3} 。
- 可能的随机序列将为{{1},{2},{3}} 。
下面是上述方法的实现。
C++
// C++ Implementation for random
// tree generator using Prufer Sequence
#include
using namespace std;
// Prints edges of tree
// represented by give Prufer code
void printTreeEdges(int prufer[], int m)
{
int vertices = m + 2;
int vertex_set[vertices];
// Initialize the array of vertices
for (int i = 0; i < vertices; i++)
vertex_set[i] = 0;
// Number of occurrences of vertex in code
for (int i = 0; i < vertices - 2; i++)
vertex_set[prufer[i] - 1] += 1;
cout<<("\nThe edge set E(G) is:\n");
int j = 0;
// Find the smallest label not present in
// prufer[].
for (int i = 0; i < vertices - 2; i++)
{
for (j = 0; j < vertices; j++)
{
// If j+1 is not present in prufer set
if (vertex_set[j] == 0)
{
// Remove from Prufer set and print
// pair.
vertex_set[j] = -1;
cout<<"(" << (j + 1) << ", "
<< prufer[i] << ") ";
vertex_set[prufer[i] - 1]--;
break;
}
}
}
j = 0;
// For the last element
for (int i = 0; i < vertices; i++)
{
if (vertex_set[i] == 0 && j == 0)
{
cout << "(" << (i + 1) << ", ";
j++;
}
else if (vertex_set[i] == 0 && j == 1)
cout << (i + 1) << ")\n";
}
}
// generate random numbers in between l an r
int ran(int l, int r)
{
return l + (rand() % (r - l + 1));
}
// Function to Generate Random Tree
void generateRandomTree(int n)
{
int length = n - 2;
int arr[length];
// Loop to Generate Random Array
for (int i = 0; i < length; i++)
{
arr[i] = ran(0, length + 1) + 1;
}
printTreeEdges(arr, length);
}
// Driver Code
int main()
{
srand(time(0));
int n = 5;
generateRandomTree(n);
return 0;
}
// This code is contributed by Arnab Kundu
Java
// Java Implementation for random
// tree generator using Prufer Sequence
import java.util.Arrays;
import java.util.Random;
class GFG {
// Prints edges of tree
// represented by give Prufer code
static void printTreeEdges(int prufer[], int m)
{
int vertices = m + 2;
int vertex_set[] = new int[vertices];
// Initialize the array of vertices
for (int i = 0; i < vertices; i++)
vertex_set[i] = 0;
// Number of occurrences of vertex in code
for (int i = 0; i < vertices - 2; i++)
vertex_set[prufer[i] - 1] += 1;
System.out.print("\nThe edge set E(G) is:\n");
int j = 0;
// Find the smallest label not present in
// prufer[].
for (int i = 0; i < vertices - 2; i++) {
for (j = 0; j < vertices; j++) {
// If j+1 is not present in prufer set
if (vertex_set[j] == 0) {
// Remove from Prufer set and print
// pair.
vertex_set[j] = -1;
System.out.print("(" + (j + 1) + ", "
+ prufer[i] + ") ");
vertex_set[prufer[i] - 1]--;
break;
}
}
}
j = 0;
// For the last element
for (int i = 0; i < vertices; i++) {
if (vertex_set[i] == 0 && j == 0) {
System.out.print("(" + (i + 1) + ", ");
j++;
}
else if (vertex_set[i] == 0 && j == 1)
System.out.print((i + 1) + ")\n");
}
}
// Function to Generate Random Tree
static void generateRandomTree(int n)
{
Random rand = new Random();
int length = n - 2;
int[] arr = new int[length];
// Loop to Generate Random Array
for (int i = 0; i < length; i++) {
arr[i] = rand.nextInt(length + 1) + 1;
}
printTreeEdges(arr, length);
}
// Driver Code
public static void main(String[] args)
{
int n = 5;
generateRandomTree(n);
}
}
C#
// C# Implementation for random
// tree generator using Prufer Sequence
using System;
class GFG
{
// Prints edges of tree
// represented by give Prufer code
static void printTreeEdges(int []prufer, int m)
{
int vertices = m + 2;
int []vertex_set = new int[vertices];
// Initialize the array of vertices
for (int i = 0; i < vertices; i++)
vertex_set[i] = 0;
// Number of occurrences of vertex in code
for (int i = 0; i < vertices - 2; i++)
vertex_set[prufer[i] - 1] += 1;
Console.Write("\nThe edge set E(G) is:\n");
int j = 0;
// Find the smallest label not present in
// prufer[].
for (int i = 0; i < vertices - 2; i++)
{
for (j = 0; j < vertices; j++)
{
// If j + 1 is not present in prufer set
if (vertex_set[j] == 0)
{
// Remove from Prufer set and print
// pair.
vertex_set[j] = -1;
Console.Write("(" + (j + 1) + ", "
+ prufer[i] + ") ");
vertex_set[prufer[i] - 1]--;
break;
}
}
}
j = 0;
// For the last element
for (int i = 0; i < vertices; i++)
{
if (vertex_set[i] == 0 && j == 0)
{
Console.Write("(" + (i + 1) + ", ");
j++;
}
else if (vertex_set[i] == 0 && j == 1)
Console.Write((i + 1) + ")\n");
}
}
// Function to Generate Random Tree
static void generateRandomTree(int n)
{
Random rand = new Random();
int length = n - 2;
int[] arr = new int[length];
// Loop to Generate Random Array
for (int i = 0; i < length; i++)
{
arr[i] = rand.Next(length + 1) + 1;
}
printTreeEdges(arr, length);
}
// Driver Code
public static void Main(String[] args)
{
int n = 5;
generateRandomTree(n);
}
}
// This code is contributed by 29AjayKumar
输出:
The edge set E(G) is:
(2, 4) (4, 3) (3, 1) (1, 5)