📜  需要从无向图上移除以使其变为非循环的最小边数

📅  最后修改于: 2021-04-22 08:31:08             🧑  作者: Mango

给定一个无向图,该无向图由N个节点组成,这些节点包含矩阵Edges [] []中的值[1,N]M个边缘,范围是确定要删除的最小边数,以便结果图可以不包含任何周期。

例子:

天真的方法:最简单的方法是尝试从给定图上逐一删除边的序列的所有可能组合,对于每种组合,计算使图成为非循环所需的去除次数。最后,在这些组合中,选择删除最小数量的边以获得无环图的组合。  
时间复杂度: O(M!)
辅助空间: O(N + M)

高效的方法:可以基于以下观察来优化上述方法:

  1. 图是时是非循环的 或一片森林(不连贯的树木群)。
  2. 具有C个节点的树将具有( C – 1 )个边。
  3. 如果从C 1K有连接的组件 C K ,则要去除的最小边数等于:

请按照以下步骤解决问题:

  1. 使用DFS从给定图中查找已连接组件的数量。
  2. 考虑到连接的组件数为K ,则打印M – N + K作为要去除的最小边数,以使结果图形变为非循环。

下面是上述方法的实现:

C++
// C++ Program to implement
// the above approach
  
#include 
using namespace std;
  
// Stores the adjacency list
vector vec[100001];
  
// Stores if a vertex is
// visited or not
bool vis[100001];
int cc = 1;
  
// Function to perform DFS Traversal
// to count the number and size of
// all connected components
void dfs(int node)
{
    // Mark the current node as visited
    vis[node] = true;
  
    // Traverse the adjacency list
    // of the current node
    for (auto x : vec[node]) {
  
        // For every unvisited node
        if (!vis[x]) {
            cc++;
  
            // Recursive DFS Call
            dfs(x);
        }
    }
}
  
// Function to add undirected
// edge in the graph
void addEdge(int u, int v)
{
    vec[u].push_back(v);
    vec[v].push_back(u);
}
  
// Function to calculate minimum
// number of edges to be removed
void minEdgeRemoved(int N, int M,
                    int Edges[][2])
{
  
    // Create Adjacency list
    for (int i = 0; i < M; i++) {
        addEdge(Edges[i][0],
                Edges[i][1]);
    }
  
    memset(vis, false, sizeof(vis));
    int k = 0;
  
    // Iterate over all the nodes
    for (int i = 1; i <= N; i++) {
        if (!vis[i]) {
            cc = 1;
            dfs(i);
            k++;
        }
    }
  
    // Print the final count
    cout << M - N + k << endl;
}
  
// Driver Code
int main()
{
    int N = 3, M = 2;
  
    int Edges[][2] = { { 1, 2 }, { 2, 3 } };
  
    minEdgeRemoved(N, M, Edges);
}


Java
// Java program to implement
// the above approach
import java.util.*;
  
class GFG{
  
// Stores the adjacency list
@SuppressWarnings("unchecked")
static Vector []vec = new Vector[100001];
  
// Stores if a vertex is
// visited or not
static boolean []vis = new boolean[100001];
static int cc = 1;
  
// Function to perform DFS Traversal
// to count the number and size of
// all connected components
static void dfs(int node)
{
      
    // Mark the current node as visited
    vis[node] = true;
  
    // Traverse the adjacency list
    // of the current node
    for(int x : vec[node])
    {
          
        // For every unvisited node
        if (!vis[x])
        {
            cc++;
  
            // Recursive DFS call
            dfs(x);
        }
    }
}
  
// Function to add undirected
// edge in the graph
static void addEdge(int u, int v)
{
    vec[u].add(v);
    vec[v].add(u);
}
  
// Function to calculate minimum
// number of edges to be removed
static void minEdgeRemoved(int N, int M,
                           int Edges[][])
{
      
    // Create Adjacency list
    for(int i = 0; i < M; i++)
    {
        addEdge(Edges[i][0],
                Edges[i][1]);
    }
  
    int k = 0;
  
    // Iterate over all the nodes
    for(int i = 1; i <= N; i++)
    {
        if (!vis[i])
        {
            cc = 1;
            dfs(i);
            k++;
        }
    }
  
    // Print the final count
    System.out.print(M - N + k + "\n");
}
  
// Driver Code
public static void main(String[] args)
{
    int N = 3, M = 2;
  
    int Edges[][] = { { 1, 2 }, { 2, 3 } };
      
    for(int i = 0; i < vec.length; i++)
        vec[i] = new Vector();
          
    minEdgeRemoved(N, M, Edges);
}
}
  
// This code is contributed by 29AjayKumar


Python3
# Python3 program to implement
# the above approach
  
# Stores the adjacency list
vec = [[] for i in range(100001)]
  
# Stores if a vertex is
# visited or not
vis = [False] * 100001
cc = 1
  
# Function to perform DFS Traversal
# to count the number and size of
# all connected components
def dfs(node):
      
    global cc
      
    # Mark the current node as visited
    vis[node] = True
  
    # Traverse the adjacency list
    # of the current node
    for x in vec[node]:
  
        # For every unvisited node
        if (vis[x] == 0):
            cc += 1
  
            # Recursive DFS Call
            dfs(x)
  
# Function to add undirected
# edge in the graph
def addEdge(u, v):
      
    vec[u].append(v)
    vec[v].append(u)
  
# Function to calculate minimum
# number of edges to be removed
def minEdgeRemoved(N, M, Edges):
      
    global cc
  
    # Create Adjacency list
    for i in range(M):
        addEdge(Edges[i][0], Edges[i][1])
  
    # memset(vis, false, sizeof(vis))
    k = 0
  
    # Iterate over all the nodes
    for i in range(1, N + 1):
        if (not vis[i]):
            cc = 1
            dfs(i)
            k += 1
  
    # Print the final count
    print(M - N + k)
  
# Driver Code
if __name__ == '__main__':
      
    N = 3
    M = 2
  
    Edges = [ [ 1, 2 ], [ 2, 3 ] ]
  
    minEdgeRemoved(N, M, Edges)
  
# This code is contributed by mohit kumar 29


C#
// C# program to implement
// the above approach
using System;
using System.Collections.Generic;
  
class GFG{
  
// Stores the adjacency list
static List []vec = new List[100001];
  
// Stores if a vertex is
// visited or not
static bool []vis = new bool[100001];
static int cc = 1;
  
// Function to perform DFS Traversal
// to count the number and size of
// all connected components
static void dfs(int node)
{
      
    // Mark the current node as visited
    vis[node] = true;
  
    // Traverse the adjacency list
    // of the current node
    foreach(int x in vec[node])
    {
          
        // For every unvisited node
        if (!vis[x])
        {
            cc++;
  
            // Recursive DFS call
            dfs(x);
        }
    }
}
  
// Function to add undirected
// edge in the graph
static void addEdge(int u, int v)
{
    vec[u].Add(v);
    vec[v].Add(u);
}
  
// Function to calculate minimum
// number of edges to be removed
static void minEdgeRemoved(int N, int M,
                           int [,]Edges)
{
      
    // Create Adjacency list
    for(int i = 0; i < M; i++)
    {
        addEdge(Edges[i, 0],
                Edges[i, 1]);
    }
  
    int k = 0;
  
    // Iterate over all the nodes
    for(int i = 1; i <= N; i++)
    {
        if (!vis[i])
        {
            cc = 1;
            dfs(i);
            k++;
        }
    }
  
    // Print the readonly count
    Console.Write(M - N + k + "\n");
}
  
// Driver Code
public static void Main(String[] args)
{
    int N = 3, M = 2;
  
    int [,]Edges = { { 1, 2 }, { 2, 3 } };
      
    for(int i = 0; i < vec.Length; i++)
        vec[i] = new List();
          
    minEdgeRemoved(N, M, Edges);
}
}
  
// This code is contributed by 29AjayKumar


输出:
0

时间复杂度: O(N + M)
辅助空间: O(N + M)