📜  将有向图转换为树

📅  最后修改于: 2021-10-25 04:41:50             🧑  作者: Mango

给定一个大小为N的数组arr[] 。从iarr[i]有一条边。任务是通过改变一些边将这个有向图转换成树。如果对于某些iarr[i] = i那么i代表树的根。如果有多个答案,请打印其中任何一个。
例子:

方法:考虑上面的第二个示例图像,它显示了一个功能图的示例。它由两个循环 1, 6, 3 和 4 组成。我们的目标是使图由恰好一个循环的恰好一个顶点循环到自身组成。
变化的操作相当于移除一些外向边并添加一条新的边,到达其他顶点。让我们首先让我们的图只包含一个循环。为此,人们可以选择任何最初呈现的周期并说它将是唯一的周期。然后应该考虑每隔一个循环,删除它的任何循环边,并用一条通往所选循环的任何顶点的边替换它。因此,循环将被打破,它的顶点(以及树的顶点)将连接到唯一选择的循环。人们将需要精确地执行cycleCount – 1这样的操作。请注意,删除任何非循环边都没有意义,因为它不会破坏任何循环。
下一步是使循环长度等于 1。这可能已经满足了,如果选择一个最小长度的循环并且这个长度等于 1。因此,如果初始图包含任何长度为 1 的循环,我们是使用cycleCount – 1 次操作完成。否则,循环包含多个顶点。它可以通过一个操作来修复——只需要打破任何循环中的边,比如从 u 到 arr[u],并添加从 u 到 u 的边。该图将保持由一个循环组成,但由一个自循环顶点组成。在这种情况下,我们完成了 cycleCount 操作。
要完成上述所有操作,可以使用 DSU 结构,或者只是一系列 DFS。注意,边去除和边创建的实现不需要,只需要分析初始图即可。
下面是上述方法的实现:

C++
// CPP program to convert directed graph into tree
#include 
using namespace std;
 
// Function to find root of the vertex
int find(int x, int a[], int vis[], int root[])
{
    if (vis[x])
        return root[x];
 
    vis[x] = 1;
    root[x] = x;
    root[x] = find(a[x], a, vis, root);
    return root[x];
}
 
// Function to convert directed graph into tree
void Graph_to_tree(int a[], int n)
{
    // Vis array to check if an index is visited or not
    // root[] array is to store parent of each vertex
    int vis[n] = { 0 }, root[n] = { 0 };
 
    // Find parent of each parent
    for (int i = 0; i < n; i++)
        find(a[i], a, vis, root);
 
    // par stores the root of the resulting tree
    int par = -1;
    for (int i = 0; i < n; i++)
        if (i == a[i])
            par = i;
 
    // If no self loop exists
    if (par == -1) {
        for (int i = 0; i < n; i++) {
 
            // Make vertex in a cycle as root of the tree
            if (i == find(a[i], a, vis, root)) {
                par = i;
                a[i] = i;
                break;
            }
        }
    }
 
    // Remove all cycles
    for (int i = 0; i < n; i++) {
        if (i == find(a[i], a, vis, root)) {
            a[i] = par;
        }
    }
 
    // Print the resulting array
    for (int i = 0; i < n; i++)
        cout << a[i] << " ";
}
 
// Driver code to test above functions
int main()
{
    int a[] = { 6, 6, 0, 1, 4, 3, 3, 4, 0 };
 
    int n = sizeof(a) / sizeof(a[0]);
 
    // Function call
    Graph_to_tree(a, n);
}


Java
// Java program to convert
// directed graph into tree
import java.util.*;
     
class GFG
{
 
// Function to find root of the vertex
static int find(int x, int a[],
                int vis[], int root[])
{
    if (vis[x] == 1)
        return root[x];
 
    vis[x] = 1;
    root[x] = x;
    root[x] = find(a[x], a, vis, root);
    return root[x];
}
 
// Function to convert directed graph into tree
static void Graph_to_tree(int a[], int n)
{
    // Vis array to check if an index is
    // visited or not root[] array is to
    // store parent of each vertex
    int []vis = new int[n];
    int []root = new int[n];
 
    // Find parent of each parent
    for (int i = 0; i < n; i++)
        find(a[i], a, vis, root);
 
    // par stores the root of the resulting tree
    int par = -1;
    for (int i = 0; i < n; i++)
        if (i == a[i])
            par = i;
 
    // If no self loop exists
    if (par == -1)
    {
        for (int i = 0; i < n; i++)
        {
 
            // Make vertex in a cycle as root of the tree
            if (i == find(a[i], a, vis, root))
            {
                par = i;
                a[i] = i;
                break;
            }
        }
    }
 
    // Remove all cycles
    for (int i = 0; i < n; i++)
    {
        if (i == find(a[i], a, vis, root))
        {
            a[i] = par;
        }
    }
 
    // Print the resulting array
    for (int i = 0; i < n; i++)
        System.out.print(a[i] + " ");
}
 
// Driver Code
static public void main ( String []arr)
{
    int a[] = { 6, 6, 0, 1, 4, 3, 3, 4, 0 };
 
    int n = a.length;
 
    // Function call
    Graph_to_tree(a, n);
}
}
 
// This code is contributed by 29AjayKumar


Python3
# A Python3 program to convert
# directed graph into tree
 
# Function to find root of the vertex
def find(x, a, vis, root):
    if vis[x]:
        return root[x]
 
    vis[x] = 1
    root[x] = x
    root[x] = find(a[x], a, vis, root)
    return root[x]
 
# Function to convert directed graph into tree
def Graph_To_Tree(a, n):
 
    # Vis array to check if an index is visited or not
    # root[] array is to store parent of each vertex
    vis = [0] * n
    root = [0] * n
 
    # Find parent of each parent
    for i in range(n):
        find(a[i], a, vis, root)
 
    # par stores the root of the resulting tree
    par = -1
    for i in range(n):
        if i == a[i]:
            par = i
 
    # If no self loop exists
    if par == -1:
        for i in range(n):
 
            # Make vertex in a cycle as root of the tree
            if i == find(a[i], a, vis, root):
                par = i
                a[i] = i
                break
 
    # Remove all cycles
    for i in range(n):
        if i == find(a[i], a, vis, root):
            a[i] = par
 
    # Print the resulting array
    for i in range(n):
        print(a[i], end = " ")
 
# Driver Code
if __name__ == "__main__":
    a = [6, 6, 0, 1, 4, 3, 3, 4, 0]
    n = len(a)
 
    # Function call
    Graph_To_Tree(a, n)
 
# This code is contributed by
# sanjeev2552


C#
// C# program to convert
// directed graph into tree
using System;
using System.Collections.Generic;
 
class GFG
{
 
// Function to find root of the vertex
static int find(int x, int []a,
                int []vis, int []root)
{
    if (vis[x] == 1)
        return root[x];
 
    vis[x] = 1;
    root[x] = x;
    root[x] = find(a[x], a, vis, root);
    return root[x];
}
 
// Function to convert directed graph into tree
static void Graph_to_tree(int []a, int n)
{
    // Vis array to check if an index is
    // visited or not root[] array is to
    // store parent of each vertex
    int []vis = new int[n];
    int []root = new int[n];
 
    // Find parent of each parent
    for (int i = 0; i < n; i++)
        find(a[i], a, vis, root);
 
    // par stores the root of the resulting tree
    int par = -1;
    for (int i = 0; i < n; i++)
        if (i == a[i])
            par = i;
 
    // If no self loop exists
    if (par == -1)
    {
        for (int i = 0; i < n; i++)
        {
 
            // Make vertex in a cycle as root of the tree
            if (i == find(a[i], a, vis, root))
            {
                par = i;
                a[i] = i;
                break;
            }
        }
    }
 
    // Remove all cycles
    for (int i = 0; i < n; i++)
    {
        if (i == find(a[i], a, vis, root))
        {
            a[i] = par;
        }
    }
 
    // Print the resulting array
    for (int i = 0; i < n; i++)
        Console.Write(a[i] + " ");
}
 
// Driver Code
static public void Main ( String []arr)
{
    int []a = { 6, 6, 0, 1, 4, 3, 3, 4, 0 };
 
    int n = a.Length;
 
    // Function call
    Graph_to_tree(a, n);
}
}
 
// This code is contributed by Princi Singh


Javascript


输出:
6 6 0 1 4 3 4 4 0

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程