给定一个由N 个节点组成的无向图,其中包含范围[1, N]和矩阵Edges[][]中的M 条边的值,任务是确定需要删除的最小边数,以便结果图不包含任何循环。
例子:
Input: N = 3, M = 3, edges[][] = [[1, 2], [2, 3], [3, 1]]
Output: 1
Explanation:
Removing any one of the edges will make the graph acyclic. Therefore, at least one edge needs to be removed.
Input: N = 3, M = 2, edges[][] = [[1, 2], [2, 3]]
Output: 0
Explanation: Graph is already acyclic. Therefore, no edge removal is required.
朴素的方法:最简单的方法是尝试从给定的图中一一删除所有可能的边序列组合,并为每个组合计算使图无环所需的删除次数。最后,在这些组合中,选择删除边数最少的组合,得到一个无环图。
时间复杂度: O(M!)
辅助空间: O(N + M)
高效的方法:上述方法可以基于以下观察进行优化:
- 当图是树时,图是无环的 或一片树林(断开的树群)。
- 具有C 个节点的树将具有 ( C – 1 ) 条边。
- 如果有K 个连通分量从C 1到 C K ,则要移除的最小边数等于:
M – (C1 – 1) – (C2 – 1) … (Ck -1 )
=> M – (C1 + … + CK) + K
=> M – N + K
请按照以下步骤解决问题:
- 使用 DFS 从给定图中找出连通分量的数量。
- 考虑到连通分量的数量为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)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live