给定一个大小为N的数组arr[] 。从i到arr[i]有一条边。任务是通过改变一些边将这个有向图转换成树。如果对于某些i , arr[i] = i那么i代表树的根。如果有多个答案,请打印其中任何一个。
例子:
Input: arr[] = {6, 6, 0, 1, 4, 3, 3, 4, 0}
Output: {6, 6, 0, 1, 4, 3, 4, 4, 0}
Input: arr[] = {1, 2, 0};
Output: {0, 2, 0}.
方法:考虑上面的第二个示例图像,它显示了一个功能图的示例。它由两个循环 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 现场工作专业课程和学生竞争性编程现场课程。