📌  相关文章
📜  计算改变边方向的方法,使图变得无环

📅  最后修改于: 2021-09-05 08:47:20             🧑  作者: Mango

给定一个由N个顶点和一个数组arr[]组成的有向和未加权图,其中第 i 个顶点具有到arr[i] 的有向边。任务是找到改变边方向的方法的数量,使得给定的图是无环的。

例子:

方法:想法是检查Connected Components是否形成循环。

  • 如果组件是路径,那么我们将边缘定向,我们不会形成循环。
  • 如果组件有一个带有 N 条边的环,那么有2 N种方式可以排列所有边,其中只有 2 种方式会形成一个环。所以有(2 N – 2)种方法可以改变边,使图变为无环。

步骤

  1. 使用深度优先搜索 (DFS) 遍历查找给定图中的循环以及与每个循环关联的顶点数。
  2. 经过 DFS 遍历后,改变边方向的方式总数为以下乘积:
    • X顶点的每个循环形成的路数由(2 X – 2) 给出
    • Y顶点的每条路径形成的路数由(2 Y ) 给出

下面是上述方法的实现:

C++
// C++ program to count the
// number of ways to change
// the direction of edges
// such that no cycle is
// present in the graph
#include 
using namespace std;
 
// Vector cycles[] to store
// the cycle with vertices
// associated with each cycle
vector cycles;
 
// Count of cycle
int cyclecnt;
 
// Function to count the
// number of vertices in the
// current cycle
void DFSUtil(int u, int arr[], int vis[])
{
    cycles[cyclecnt]++;
    vis[u] = 3;
 
    // Returns when the same
    // initial vertex is found
    if (vis[arr[u]] == 3) {
        return;
    }
 
    // Recurr for next vertex
    DFSUtil(arr[u], arr, vis);
}
 
// DFS traversal to detect
// the cycle in graph
void DFS(int u, int arr[], int vis[])
{
    // Marke vis[u] to 2 to
    // check for any cycle form
    vis[u] = 2;
 
    // If the vertex arr[u]
    // is not visited
    if (vis[arr[u]] == 0) {
        // Call DFS
        DFS(arr[u], arr, vis);
    }
 
    // If current node is
    // processed
    else if (vis[arr[u]] == 1) {
        vis[u] = 1;
        return;
    }
 
    // Cycle found, call DFSUtil
    // to count the number of
    // vertices in the current
    // cycle
    else {
        cycles.push_back(0);
 
        // Count number of
        // vertices in cycle
        DFSUtil(u, arr, vis);
        cyclecnt++;
    }
 
    // Current Node is processed
    vis[u] = 1;
}
 
// Function to count the
// number of ways
int countWays(int arr[], int N)
{
 
    int i, ans = 1;
 
    // To precompute the power
    // of 2
    int dp[N + 1];
    dp[0] = 1;
 
    // Storing power of 2
    for (int i = 1; i <= N; i++) {
        dp[i] = (dp[i - 1] * 2);
    }
 
    // Array vis[] created for
    // DFS traversal
    int vis[N + 1] = { 0 };
 
    // DFS traversal from Node 1
    for (int i = 1; i <= N; i++) {
        if (vis[i] == 0) {
 
            // Calling DFS
            DFS(i, arr, vis);
        }
    }
 
    int cnt = N;
 
    // Traverse the cycles array
    for (i = 0; i < cycles.size(); i++) {
 
        // Remove the vertices
        // which are part of a
        // cycle
        cnt -= cycles[i];
 
        // Count form by number
        // vertices form cycle
        ans *= dp[cycles[i]] - 2;
    }
 
    // Count form by number of
    // vertices not forming
    // cycle
    ans = (ans * dp[cnt]);
 
    return ans;
}
 
// Driver's Code
int main()
{
    int N = 3;
    int arr[] = { 0, 2, 3, 1 };
 
    // Function to count ways
    cout << countWays(arr, N);
    return 0;
}


Java
// Java program to count the number
// of ways to change the direction
// of edges such that no cycle is
// present in the graph
import java.util.*;
import java.lang.*;
import java.io.*;
 
class GFG{
     
// Vector cycles[] to store
// the cycle with vertices
// associated with each cycle
static ArrayList cycles;
   
// Count of cycle
static int cyclecnt;
   
// Function to count the
// number of vertices in the
// current cycle
static void DFSUtil(int u, int arr[],
                           int vis[])
{
    cycles.set(cyclecnt,
    cycles.get(cyclecnt) + 1);
    vis[u] = 3;
   
    // Returns when the same
    // initial vertex is found
    if (vis[arr[u]] == 3)
    {
        return;
    }
   
    // Recurr for next vertex
    DFSUtil(arr[u], arr, vis);
}
   
// DFS traversal to detect
// the cycle in graph
static void DFS(int u, int arr[], int vis[])
{
     
    // Marke vis[u] to 2 to
    // check for any cycle form
    vis[u] = 2;
   
    // If the vertex arr[u]
    // is not visited
    if (vis[arr[u]] == 0)
    {
         
        // Call DFS
        DFS(arr[u], arr, vis);
    }
   
    // If current node is
    // processed
    else if (vis[arr[u]] == 1)
    {
        vis[u] = 1;
        return;
    }
   
    // Cycle found, call DFSUtil
    // to count the number of
    // vertices in the current
    // cycle
    else
    {
        cycles.add(0);
   
        // Count number of
        // vertices in cycle
        DFSUtil(u, arr, vis);
        cyclecnt++;
    }
   
    // Current Node is processed
    vis[u] = 1;
}
   
// Function to count the
// number of ways
static int countWays(int arr[], int N)
{
    int i, ans = 1;
   
    // To precompute the power
    // of 2
    int[] dp = new int[N + 1];
    dp[0] = 1;
   
    // Storing power of 2
    for(i = 1; i <= N; i++)
    {
        dp[i] = (dp[i - 1] * 2);
    }
   
    // Array vis[] created for
    // DFS traversal
    int[] vis = new int[N + 1];
   
    // DFS traversal from Node 1
    for(i = 1; i <= N; i++)
    {
        if (vis[i] == 0)
        {
             
            // Calling DFS
            DFS(i, arr, vis);
        }
    }
   
    int cnt = N;
   
    // Traverse the cycles array
    for(i = 0; i < cycles.size(); i++)
    {
   
        // Remove the vertices
        // which are part of a
        // cycle
        cnt -= cycles.get(i);
   
        // Count form by number
        // vertices form cycle
        ans *= dp[cycles.get(i)] - 2;
    }
   
    // Count form by number of
    // vertices not forming
    // cycle
    ans = (ans * dp[cnt]);
   
    return ans;
}
   
// Driver code
public static void main(String[] args)
{
    int N = 3;
    int arr[] = { 0, 2, 3, 1 };
     
    cycles = new ArrayList<>();
     
    // Function to count ways
    System.out.println(countWays(arr, N));
}
}
 
// This code is contributed by offbeat


Python3
# Python3 program to count the
# number of ways to change
# the direction of edges
# such that no cycle is
# present in the graph
 
# List cycles[] to store
# the cycle with vertices
# associated with each cycle
cycles = []
 
# Function to count the
# number of vertices in the
# current cycle
def DFSUtil(u, arr, vis, cyclecnt):
 
    cycles[cyclecnt] += 1
    vis[u] = 3
 
    # Returns when the same
    # initial vertex is found
    if (vis[arr[u]] == 3) :
        return
 
    # Recurr for next vertex
    DFSUtil(arr[u], arr, vis, cyclecnt)
 
# DFS traversal to detect
# the cycle in graph
def DFS( u, arr, vis, cyclecnt):
 
    # Marke vis[u] to 2 to
    # check for any cycle form
    vis[u] = 2
 
    # If the vertex arr[u]
    # is not visited
    if (vis[arr[u]] == 0) :
         
        # Call DFS
        DFS(arr[u], arr, vis, cyclecnt)
 
    # If current node is
    # processed
    elif (vis[arr[u]] == 1):
        vis[u] = 1
        return
 
    # Cycle found, call DFSUtil
    # to count the number of
    # vertices in the current
    # cycle
    else :
        cycles.append(0)
 
        # Count number of
        # vertices in cycle
        DFSUtil(u, arr, vis,cyclecnt)
        cyclecnt += 1
 
    # Current Node is processed
    vis[u] = 1
 
# Function to count the
# number of ways
def countWays(arr, N,cyclecnt):
 
    ans = 1
 
    # To precompute the power
    # of 2
    dp = [0]*(N + 1)
    dp[0] = 1
 
    # Storing power of 2
    for i in range(1, N + 1):
        dp[i] = (dp[i - 1] * 2)
 
    # Array vis[] created for
    # DFS traversal
    vis = [0]*(N + 1)
 
    # DFS traversal from Node 1
    for i in range(1, N + 1) :
        if (vis[i] == 0) :
 
            # Calling DFS
            DFS(i, arr, vis, cyclecnt)
 
    cnt = N
 
    # Traverse the cycles array
    for i in range(len(cycles)) :
 
        # Remove the vertices
        # which are part of a
        # cycle
        cnt -= cycles[i]
 
        # Count form by number
        # vertices form cycle
        ans *= dp[cycles[i]] - 2
 
    # Count form by number of
    # vertices not forming
    # cycle
    ans = (ans * dp[cnt])
 
    return ans
 
# Driver's Code
if __name__ == "__main__":
     
    N = 3
    cyclecnt = 0
    arr = [ 0, 2, 3, 1 ]
 
    # Function to count ways
    print(countWays(arr, N,cyclecnt))
     
# This code is contributed by chitranayal


C#
// C# program to count the number
// of ways to change the direction
// of edges such that no cycle is
// present in the graph
using System;
using System.Collections;
using System.Collections.Generic;
  
class GFG{
      
// Vector cycles[] to store
// the cycle with vertices
// associated with each cycle
static ArrayList cycles;
    
// Count of cycle
static int cyclecnt;
    
// Function to count the
// number of vertices in the
// current cycle
static void DFSUtil(int u, int []arr,
                           int []vis)
{
    cycles[cyclecnt] = (int)cycles[cyclecnt] + 1;
    vis[u] = 3;
     
    // Returns when the same
    // initial vertex is found
    if (vis[arr[u]] == 3)
    {
        return;
    }
     
    // Recurr for next vertex
    DFSUtil(arr[u], arr, vis);
}
    
// DFS traversal to detect
// the cycle in graph
static void DFS(int u, int []arr, int []vis)
{
     
    // Marke vis[u] to 2 to
    // check for any cycle form
    vis[u] = 2;
    
    // If the vertex arr[u]
    // is not visited
    if (vis[arr[u]] == 0)
    {
         
        // Call DFS
        DFS(arr[u], arr, vis);
    }
    
    // If current node is
    // processed
    else if (vis[arr[u]] == 1)
    {
        vis[u] = 1;
        return;
    }
    
    // Cycle found, call DFSUtil
    // to count the number of
    // vertices in the current
    // cycle
    else
    {
        cycles.Add(0);
         
        // Count number of
        // vertices in cycle
        DFSUtil(u, arr, vis);
        cyclecnt++;
    }
     
    // Current Node is processed
    vis[u] = 1;
}
    
// Function to count the
// number of ways
static int countWays(int []arr, int N)
{
    int i, ans = 1;
     
    // To precompute the power
    // of 2
    int[] dp = new int[N + 1];
    dp[0] = 1;
    
    // Storing power of 2
    for(i = 1; i <= N; i++)
    {
        dp[i] = (dp[i - 1] * 2);
    }
    
    // Array vis[] created for
    // DFS traversal
    int[] vis = new int[N + 1];
    
    // DFS traversal from Node 1
    for(i = 1; i <= N; i++)
    {
        if (vis[i] == 0)
        {
             
            // Calling DFS
            DFS(i, arr, vis);
        }
    }
    
    int cnt = N;
    
    // Traverse the cycles array
    for(i = 0; i < cycles.Count; i++)
    {
         
        // Remove the vertices
        // which are part of a
        // cycle
        cnt -= (int)cycles[i];
         
        // Count form by number
        // vertices form cycle
        ans *= dp[(int)cycles[i]] - 2;
    }
     
    // Count form by number of
    // vertices not forming
    // cycle
    ans = (ans * dp[cnt]);
    
    return ans;
}
    
// Driver code
public static void Main(string[] args)
{
    int N = 3;
    int []arr = new int[]{ 0, 2, 3, 1 };
      
    cycles = new ArrayList();
      
    // Function to count ways
    Console.Write(countWays(arr, N));
}
}
 
// This code is contributed by rutvik_56


Javascript


输出:
6

时间复杂度: O(V + E)

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live