Open In App

Test case generator for Tree using Disjoint-Set Union

Improve
Improve
Like Article
Like
Save
Share
Report

In this article, we will generate test cases such that given set edges form a Tree. Below are the two conditions of the Tree:

  • It should have one less edge than the number of vertices.
  • There should be no cycle in it.

Approach: The idea is to run a loop and add one edge each time that is generated randomly, and for adding each edge we will check whether it is forming cycle or not. We can ensure that cycle is present or not with the help of Disjoint-Set Union. If adding any edges form cycle then ignore the current edges and generate the new set of edges. Else print the edges with randomly generated weight. Below is the implementation of the above approach: 

C++




// C++ implementation to generate
// test-case for the Tree
 
#include <bits/stdc++.h>
using namespace std;
 
typedef long long int ll;
#define fast ios_base::sync_with_stdio(false);
#define MOD 1000000007
 
// Maximum Number Of Nodes
#define MAXNODE 10;
 
// Maximum Number Of testCases
#define MAXT 10;
 
// Maximum weight
#define MAXWEIGHT 100;
 
// Function for the path
// compression technique
ll find(ll parent[], ll x)
{
    // If parent found
    if (parent[x] == x)
        return x;
 
    // Find parent recursively
    parent[x] = find(parent, parent[x]);
 
    // Return the parent node of x
    return parent[x];
}
 
// Function to compute the union
// by rank
void merge(ll parent[], ll size[],
           ll x, ll y)
{
    ll r1 = find(parent, x);
    ll r2 = find(parent, y);
 
    if (size[r1] < size[r2]) {
        parent[r1] = r2;
        size[r2] += size[r1];
    }
    else {
        parent[r2] = r1;
        size[r1] += size[r2];
    }
}
 
// Function to generate the
// test-cases for the tree
void generate()
{
    ll t;
    t = 1 + rand() % MAXT;
 
    // Number of testcases
    cout << t << "\n";
    while (t--) {
 
        // for 2<=Number of Nodes<=MAXNODE
 
        // Randomly generate number of edges
        ll n = 2 + rand() % MAXNODE;
        ll i;
        cout << n << "\n";
        ll parent[n + 1];
        ll size[n + 1];
 
        // Initialise parent and
        // size arrays
        for (i = 1; i <= n; i++) {
            parent[i] = i;
            size[i] = 1;
        }
 
        vector<pair<ll, ll> > Edges;
        vector<ll> weights;
 
        // Now We have add N-1 edges
        for (i = 1; i <= n - 1; i++) {
            ll x = 1 + rand() % n;
            ll y = 1 + rand() % n;
 
            // Find edges till it does not
            // forms a cycle
            while (find(parent, x)
                   == find(parent, y)) {
 
                x = 1 + rand() % n;
                y = 1 + rand() % n;
            }
 
            // Merge the nodes in tree
            merge(parent, size, x, y);
 
            // Store the current edge and weight
            Edges.push_back(make_pair(x, y));
            ll w = 1 + rand() % MAXWEIGHT;
            weights.push_back(w);
        }
 
        // Print the set of edges
        // with weight
        for (i = 0; i < Edges.size(); i++) {
 
            cout << Edges[i].first << " "
                 << Edges[i].second;
            cout << " " << weights[i];
            cout << "\n";
        }
    }
}
 
// Driver Code
int main()
{
    // Uncomment the below line to store
    // the test data in a file
    // freopen ("output.txt", "w", stdout);
 
    // For random values every time
    srand(time(NULL));
 
    fast;
 
    generate();
}


Java




import java.util.*;
 
public class TreeTestCases {
    // Maximum Number Of Nodes
    static final int MAXNODE = 10;
    // Maximum Number Of testCases
    static final int MAXT = 10;
    // Maximum weight
    static final int MAXWEIGHT = 100;
 
    // Function for the path compression technique
    static int find(int[] parent, int x) {
        // If parent found
        if (parent[x] == x) {
            return x;
        }
        // Find parent recursively
        parent[x] = find(parent, parent[x]);
        // Return the parent node of x
        return parent[x];
    }
 
    // Function to compute the union by rank
    static void merge(int[] parent, int[] size, int x, int y) {
        int r1 = find(parent, x);
        int r2 = find(parent, y);
        if (size[r1] < size[r2]) {
            parent[r1] = r2;
            size[r2] += size[r1];
        } else {
            parent[r2] = r1;
            size[r1] += size[r2];
        }
    }
 
    // Function to generate the test-cases for the tree
    static void generate() {
        Random rand = new Random();
        // Number of testcases
        int t = rand.nextInt(MAXT) + 1;
        System.out.println(t);
        for (int i = 0; i < t; i++) {
            // for 2<=Number of Nodes<=MAXNODE
            // Randomly generate number of edges
            int n = rand.nextInt(MAXNODE - 1) + 2;
            System.out.println(n);
            int[] parent = new int[n + 1];
            int[] size = new int[n + 1];
            for (int j = 1; j <= n; j++) {
                parent[j] = j;
                size[j] = 1;
            }
            List<int[]> edges = new ArrayList<>();
            List<Integer> weights = new ArrayList<>();
            // Now We have to add N-1 edges
            for (int j = 0; j < n - 1; j++) {
                int x = rand.nextInt(n) + 1;
                int y = rand.nextInt(n) + 1;
                // Find edges till it does not forms a cycle
                while (find(parent, x) == find(parent, y)) {
                    x = rand.nextInt(n) + 1;
                    y = rand.nextInt(n) + 1;
                }
                // Merge the nodes in tree
                merge(parent, size, x, y);
                // Store the current edge and weight
                edges.add(new int[] {x, y});
                int w = rand.nextInt(MAXWEIGHT) + 1;
                weights.add(w);
            }
            // Print the set of edges with weight
            for (int j = 0; j < edges.size(); j++) {
                int[] edge = edges.get(j);
                System.out.println(edge[0] + " " + edge[1] + " " + weights.get(j));
            }
        }
    }
 
    // Driver Code
    public static void main(String[] args) {
        // For random values every time
        Random rand = new Random();
        rand.setSeed(System.currentTimeMillis());
        generate();
    }
}


Python3




# Python3 implementation to generate
# test-case for the Tree
import random
 
# Maximum Number Of Nodes
MAXNODE = 10
 
# Maximum Number Of testCases
MAXT = 10
 
# Maximum weight
MAXWEIGHT = 100
 
# Function for the path
# compression technique
def find(parent, x):
   
    # If parent found
    if parent[x] == x:
        return x
       
    # Find parent recursively
    parent[x] = find(parent, parent[x])
     
    # Return the parent node of x
    return parent[x]
 
# Function to compute the union
# by rank
def merge(parent, size, x, y):
    r1 = find(parent, x)
    r2 = find(parent, y)
 
    if size[r1] < size[r2]:
        parent[r1] = r2
        size[r2] += size[r1]
    else:
        parent[r2] = r1
        size[r1] += size[r2]
 
# Function to generate the
# test-cases for the tree
def generate():
   
    # Number of testcases
    t = random.randint(1, MAXT)
    print(t)
    for _ in range(t):
        # for 2<=Number of Nodes<=MAXNODE
 
        # Randomly generate number of edges
        n = random.randint(2, MAXNODE)
        print(n)
        parent = [i for i in range(n + 1)]
        size = [1 for _ in range(n + 1)]
        Edges = []
        weights = []
 
        # Now We have add N-1 edges
        for i in range(n - 1):
            x = random.randint(1, n)
            y = random.randint(1, n)
 
            # Find edges till it does not
            # forms a cycle
            while find(parent, x) == find(parent, y):
                x = random.randint(1, n)
                y = random.randint(1, n)
 
            # Merge the nodes in tree
            merge(parent, size, x, y)
 
            # Store the current edge and weight
            Edges.append((x, y))
            w = random.randint(1, MAXWEIGHT)
            weights.append(w)
 
        # Print the set of edges
        # with weight
        for i in range(len(Edges)):
            print(Edges[i][0], Edges[i][1], weights[i])
 
# Driver Code
if __name__ == "__main__":
   
    # Uncomment the below line to store
    # the test data in a file
    # open("output.txt", "w").close()
    # open("output.txt", "w").write(generate())
 
    # For random values every time
    random.seed(None)
 
    generate()
     
# This code is contributed by Potta Lokesh


C#




// C# implementation to generate
// test-case for the Tree
 
using System;
using System.Collections.Generic;
 
class GFG {
    static int MAXNODE = 10;
    static int MAXT = 10;
    static int MAXWEIGHT = 100;
    static int[] parent = new int[MAXNODE + 1];
    static int[] size = new int[MAXNODE + 1];
 
    // Function for the path
    // compression technique
    static int find(int[] parent, int x)
    {
        // If parent found
        if (parent[x] == x)
            return x;
 
        // Find parent recursively
        parent[x] = find(parent, parent[x]);
 
        // Return the parent node of x
        return parent[x];
    }
 
    // Function to compute the union
    // by rank
    static void merge(int[] parent, int[] size, int x,
                      int y)
    {
        int r1 = find(parent, x);
        int r2 = find(parent, y);
 
        if (size[r1] < size[r2]) {
            parent[r1] = r2;
            size[r2] += size[r1];
        }
        else {
            parent[r2] = r1;
            size[r1] += size[r2];
        }
    }
 
    // Function to generate the
    // test-cases for the tree
    static void generate()
    {
        Random rand = new Random();
 
        int t = 1 + rand.Next() % MAXT;
 
        // Number of testcases
        Console.WriteLine(t);
        while (t-- > 0) {
 
            // for 2<=Number of Nodes<=MAXNODE
 
            // Randomly generate number of edges
            int n = 2 + rand.Next() % MAXNODE;
            int i;
            Console.WriteLine(n);
 
            // Initialise parent and
            // size arrays
            for (i = 1; i <= n; i++) {
                parent[i] = i;
                size[i] = 1;
            }
 
            List<Tuple<int, int> > Edges
                = new List<Tuple<int, int> >();
            List<int> weights = new List<int>();
 
            // Now We have add N-1 edges
            for (i = 1; i <= n - 1; i++) {
                int x = 1 + rand.Next() % n;
                int y = 1 + rand.Next() % n;
 
                // Find edges till it does not
                // forms a cycle
                while (find(parent, x) == find(parent, y)) {
 
                    x = 1 + rand.Next() % n;
                    y = 1 + rand.Next() % n;
                }
 
                // Merge the nodes in tree
                merge(parent, size, x, y);
 
                // Store the current edge and weight
                Edges.Add(new Tuple<int, int>(x, y));
                int w = 1 + rand.Next() % MAXWEIGHT;
                weights.Add(w);
            }
 
            // Print the set of edges
            // with weight
            for (i = 0; i < Edges.Count; i++) {
                Console.WriteLine(Edges[i].Item1 + " "
                                  + Edges[i].Item2 + " "
                                  + weights[i]);
            }
        }
    }
 
    // Driver Code
    static void Main()
    {
        // Uncomment the below line to store
        // the test data in a file
        // System.setOut(new PrintStream(new
        // File("output.txt")));
 
        // For random values every time
        Random rand = new Random();
 
        generate();
    }
}


Javascript




// JavaScript implementation to generate
// test-case for the Tree
 
const MAXNODE = 10;
const MAXT = 10;
const MAXWEIGHT = 100;
const parent = new Array(MAXNODE + 1);
const size = new Array(MAXNODE + 1);
 
// Function for the path
// compression technique
function find(parent, x) {
  // If parent found
  if (parent[x] == x)
    return x;
 
  // Find parent recursively
  parent[x] = find(parent, parent[x]);
 
  // Return the parent node of x
  return parent[x];
}
 
// Function to compute the union
// by rank
function merge(parent, size, x, y) {
  let r1 = find(parent, x);
  let r2 = find(parent, y);
 
  if (size[r1] < size[r2]) {
    parent[r1] = r2;
    size[r2] += size[r1];
  } else {
    parent[r2] = r1;
    size[r1] += size[r2];
  }
}
 
// Function to generate the
// test-cases for the tree
function generate() {
   
 
  let t = 1 + Math.floor(Math.random() * MAXT);
 
  // Number of testcases
  console.log(t);
  while (t-- > 0) {
    // for 2<=Number of Nodes<=MAXNODE
 
    // Randomly generate number of edges
    let n = 2 + Math.floor(Math.random() * MAXNODE);
    let i;
    console.log(n);
 
    // Initialise parent and
    // size arrays
    for (i = 1; i <= n; i++) {
      parent[i] = i;
      size[i] = 1;
    }
 
    const Edges = [];
    const weights = [];
 
    // Now We have add N-1 edges
    for (i = 1; i <= n - 1; i++) {
      let x = 1 + Math.floor(Math.random() * n);
      let y = 1 + Math.floor(Math.random() * n);
 
      // Find edges till it does not
      // forms a cycle
      while (find(parent, x) == find(parent, y)) {
        x = 1 + Math.floor(Math.random() * n);
        y = 1 + Math.floor(Math.random() * n);
      }
 
      // Merge the nodes in tree
      merge(parent, size, x, y);
 
      // Store the current edge and weight
      Edges.push([x, y]);
      let w = 1 + Math.floor(Math.random() * MAXWEIGHT);
      weights.push(w);
    }
 
    // Print the set of edges
    // with weight
    for (i = 0; i < Edges.length; i++) {
      console.log(`${Edges[i][0]} ${Edges[i][1]} ${weights[i]}`);
    }
  }
}
 
// Driver Code
generate();


Output:

1
10
4 2 67
8 3 64
6 5 31
7 6 77
8 2 64
9 2 44
5 9 10
1 6 71
10 7 32

Time Complexity: O(N*logN) 
Auxiliary Space: O(1)



Last Updated : 17 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads