📜  将每条边添加到图中后找到最大组件大小

📅  最后修改于: 2021-10-25 05:03:55             🧑  作者: Mango

给定一个数组arr[][] ,其中包含用于构建具有N 个节点的无向图G的图的边,任务是在构建图时添加每条边后找到图中的最大组件大小。

例子:

朴素的方法:这个问题的朴素的方法是按顺序添加边,并在每一步应用深度优先搜索算法来找到最大组件的大小。

下面是上述方法的实现:

C++
// C++ program to find the
// maximum comake_paironent size
// after addition of each
// edge to the graph
#include 
 
using namespace std;
 
// Function to perform
// Depth First Search
// on the given graph
int dfs(int u, int visited[],
        vector* adj)
{
    // Mark visited
    visited[u] = 1;
    int size = 1;
 
    // Add each child's
    // comake_paironent size
    for (auto child : adj[u]) {
        if (!visited[child])
            size += dfs(child,
                        visited, adj);
    }
    return size;
}
 
// Function to find the maximum
// comake_paironent size
// after addition of each
// edge to the graph
void maxSize(vector > e,
             int n)
{
    // Graph in the adjacency
    // list format
    vector adj[n];
 
    // Visited array
    int visited[n];
 
    vector answer;
 
    // At each step, add a new
    // edge and apply dfs on all
    // the nodes to find the maximum
    // comake_paironent size
    for (auto edge : e) {
 
        // Add this edge to undirected graph
        adj[edge.first - 1].push_back(
            edge.second - 1);
        adj[edge.second - 1].push_back(
            edge.first - 1);
 
        // Mark all the nodes
        // as unvisited
        memset(visited, 0,
               sizeof(visited));
 
        int maxAns = 0;
 
        // Loop to perform DFS
        // and find the size
        // of the maximum comake_paironent
        for (int i = 0; i < n; i++) {
            if (!visited[i]) {
                maxAns = max(maxAns,
                             dfs(i, visited, adj));
            }
        }
        answer.push_back(maxAns);
    }
 
    // Print the answer
    for (auto i : answer) {
        cout << i << " ";
    }
}
 
// Driver code
int main()
{
    int N = 4;
    vector > E;
    E.push_back(make_pair(1, 2));
    E.push_back(make_pair(3, 4));
    E.push_back(make_pair(2, 3));
 
    maxSize(E, N);
 
    return 0;
}


Java
// Java program to find the maximum
// comake_paironent size after
// addition of each edge to the graph
import java.util.*;
 
@SuppressWarnings("unchecked")
class GFG{
     
static class pair
{
    int Key, Value;
     
    pair(int Key, int Value)
    {
        this.Key = Key;
        this.Value = Value;
    }
}
       
// Function to perform Depth First
// Search on the given graph
static int dfs(int u, int []visited,
               ArrayList []adj)
{
     
    // Mark visited
    visited[u] = 1;
    int size = 1;
   
    // Add each child's
    // comake_paironent size
    for(int child : (ArrayList)adj[u])
    {
        if (visited[child] == 0)
            size += dfs(child,
                        visited, adj);
    }
    return size;
}
   
// Function to find the maximum
// comake_paironent size after
// addition of each edge to the graph
static void maxSize(ArrayList e,
                    int n)
{
     
    // Graph in the adjacency
    // list format
    ArrayList []adj = new ArrayList[n];
      
    for(int i = 0; i < n; i++)
    {
        adj[i] = new ArrayList();
    }
      
    // Visited array
    int []visited = new int[n];
   
    ArrayList answer = new ArrayList();
   
    // At each step, add a new
    // edge and apply dfs on all
    // the nodes to find the maximum
    // comake_paironent size
    for(pair edge : (ArrayList)e)
    {
         
        // Add this edge to undirected graph
        adj[edge.Key - 1].add(
           edge.Value - 1);
        adj[edge.Value - 1].add(
              edge.Key - 1);
               
        // Mark all the nodes
        // as unvisited
        Arrays.fill(visited,0);
   
        int maxAns = 0;
   
        // Loop to perform DFS and find the
        // size of the maximum comake_paironent
        for(int i = 0; i < n; i++)
        {
            if (visited[i] == 0)
            {
                maxAns = Math.max(maxAns,
                              dfs(i, visited, adj));
            }
        }
        answer.add(maxAns);
    }
     
    // Print the answer
    for(int i : (ArrayList) answer)
    {
        System.out.print(i + " ");
    }
}
   
// Driver code
public static void main(String[] args)
{
    int N = 4;
     
    ArrayList E = new ArrayList();
    E.add(new pair(1, 2));
    E.add(new pair(3, 4));
    E.add(new pair(2, 3));
   
    maxSize(E, N);
}
}
 
// This code is contributed by pratham76


C#
// C# program to find the
// maximum comake_paironent size
// after addition of each
// edge to the graph
using System;
using System.Collections;
using System.Collections.Generic;
 
class GFG{
      
// Function to perform
// Depth First Search
// on the given graph
static int dfs(int u, int []visited,
               ArrayList []adj)
{
     
    // Mark visited
    visited[u] = 1;
    int size = 1;
  
    // Add each child's
    // comake_paironent size
    foreach (int child in adj[u])
    {
        if (visited[child] == 0)
            size += dfs(child,
                        visited, adj);
    }
    return size;
}
  
// Function to find the maximum
// comake_paironent size
// after addition of each
// edge to the graph
static void maxSize(ArrayList e,
                    int n)
{
     
    // Graph in the adjacency
    // list format
    ArrayList []adj = new ArrayList[n];
     
    for(int i = 0; i < n; i++)
    {
        adj[i] = new ArrayList();
    }
     
    // Visited array
    int []visited = new int[n];
  
    ArrayList answer = new ArrayList();
  
    // At each step, add a new
    // edge and apply dfs on all
    // the nodes to find the maximum
    // comake_paironent size
    foreach(KeyValuePair edge in e)
    {
         
        // Add this edge to undirected graph
        adj[edge.Key - 1].Add(
           edge.Value - 1);
        adj[edge.Value - 1].Add(
              edge.Key - 1);
  
        // Mark all the nodes
        // as unvisited
        Array.Fill(visited,0);
  
        int maxAns = 0;
  
        // Loop to perform DFS
        // and find the size
        // of the maximum comake_paironent
        for(int i = 0; i < n; i++)
        {
            if (visited[i] == 0)
            {
                maxAns = Math.Max(maxAns,
                              dfs(i, visited, adj));
            }
        }
        answer.Add(maxAns);
    }
  
    // Print the answer
    foreach(int i in answer)
    {
        Console.Write(i + " ");
    }
}
  
// Driver code
public static void Main(string[] args)
{
    int N = 4;
    ArrayList E = new ArrayList();
    E.Add(new KeyValuePair(1, 2));
    E.Add(new KeyValuePair(3, 4));
    E.Add(new KeyValuePair(2, 3));
  
    maxSize(E, N);
}
}
 
// This code is contributed by rutvik_56


C++
// C++ implementation to find the maximum
// component size after the addition of
// each edge to the graph
 
#include 
 
using namespace std;
 
// Variables for implementing DSU
int par[100005];
int size[100005];
 
// Root of the component of node i
int root(int i)
{
    if (par[i] == i)
        return i;
 
    // Finding the root and applying
    // path compression
    else
        return par[i] = root(par[i]);
}
 
// Function to merge two components
void merge(int a, int b)
{
 
    // Find the roots of both
    // the components
    int p = root(a);
    int q = root(b);
 
    // If both the nodes already belong
    // to the same compenent
    if (p == q)
        return;
 
    // Union by rank, the rank in
    // this case is the size of
    // the component.
    // Smaller size will be
    // merged into larger,
    // so the larger's root
    // will be the final root
    if (size[p] > size[q])
        swap(p, q);
 
    par[p] = q;
    size[q] += size[p];
}
 
// Function to find the
// maximum component size
// after the addition of
// each edge to the graph
void maxSize(vector > e, int n)
{
 
    // Initialising the disjoint set
    for (int i = 1; i < n + 1; i++) {
 
        // Each node is the root and
        // each component size is 1
        par[i] = i;
        size[i] = 1;
    }
 
    vector answer;
 
    // A multiset is being used to store
    // the size of the components
    // because multiple components
    // can have same sizes
    multiset compSizes;
    for (int i = 1; i <= n; i++)
        compSizes.insert(size[i]);
 
    // At each step; add a new edge,
    // merge the components
    // and find the max
    // sized component
    for (auto edge : e) {
 
        // Merge operation is required only when
        // both the nodes don't belong to the
        // same component
        if (root(edge.first) != root(edge.second)) {
 
            // Sizes of the compenents
            int size1 = size[root(edge.first)];
            int size2 = size[root(edge.second)];
 
            // Remove the previous component sizes
            compSizes.erase(compSizes.find(size1));
            compSizes.erase(compSizes.find(size2));
 
            // Perform the merge operation
            merge(edge.first, edge.second);
 
            // Insert the combined size
            compSizes.insert(size1 + size2);
        }
 
        // Maximum value in the multiset is
        // the max component size
        answer.push_back(*compSizes.rbegin());
    }
 
    // Printing the answer
    for (int i = 0; i < answer.size(); i++) {
        cout << answer[i] << " ";
    }
}
 
// Driver code
int main()
{
    int N = 4;
    vector > E;
    E.push_back(make_pair(1, 2));
    E.push_back(make_pair(3, 4));
    E.push_back(make_pair(2, 3));
 
    maxSize(E, N);
 
    return 0;
}


输出:
2 2 4

时间复杂度: O(|E| * N)

Efficient Approach:思路是利用Disjoint Set(Union by rank and Path compression)的概念来更高效地解决问题。

  • 每个节点最初都是一个不相交的集合。当添加边时,不相交的集合合并在一起形成更大的组件。在不相交集的实现中,我们将根据组件的大小进行排名系统,即当两个组件合并时,较大组件的根将被视为合并操作后的最终根。
  • 在每条边添加后找到最大尺寸分量的一种方法是遍历尺寸数组(size[i] 表示节点’i’所属的分量的尺寸),但是当图中的节点数为高。
  • 一种更有效的方法是将所有根的组件大小存储在某些有序数据结构(如集合)中。
  • 当两个组件合并时,我们需要做的就是从集合中删除之前的组件大小并添加组合的组件大小。因此,在每一步,我们都能够找到对数复杂度中最大的组件大小。

下面是上述方法的实现:

C++

// C++ implementation to find the maximum
// component size after the addition of
// each edge to the graph
 
#include 
 
using namespace std;
 
// Variables for implementing DSU
int par[100005];
int size[100005];
 
// Root of the component of node i
int root(int i)
{
    if (par[i] == i)
        return i;
 
    // Finding the root and applying
    // path compression
    else
        return par[i] = root(par[i]);
}
 
// Function to merge two components
void merge(int a, int b)
{
 
    // Find the roots of both
    // the components
    int p = root(a);
    int q = root(b);
 
    // If both the nodes already belong
    // to the same compenent
    if (p == q)
        return;
 
    // Union by rank, the rank in
    // this case is the size of
    // the component.
    // Smaller size will be
    // merged into larger,
    // so the larger's root
    // will be the final root
    if (size[p] > size[q])
        swap(p, q);
 
    par[p] = q;
    size[q] += size[p];
}
 
// Function to find the
// maximum component size
// after the addition of
// each edge to the graph
void maxSize(vector > e, int n)
{
 
    // Initialising the disjoint set
    for (int i = 1; i < n + 1; i++) {
 
        // Each node is the root and
        // each component size is 1
        par[i] = i;
        size[i] = 1;
    }
 
    vector answer;
 
    // A multiset is being used to store
    // the size of the components
    // because multiple components
    // can have same sizes
    multiset compSizes;
    for (int i = 1; i <= n; i++)
        compSizes.insert(size[i]);
 
    // At each step; add a new edge,
    // merge the components
    // and find the max
    // sized component
    for (auto edge : e) {
 
        // Merge operation is required only when
        // both the nodes don't belong to the
        // same component
        if (root(edge.first) != root(edge.second)) {
 
            // Sizes of the compenents
            int size1 = size[root(edge.first)];
            int size2 = size[root(edge.second)];
 
            // Remove the previous component sizes
            compSizes.erase(compSizes.find(size1));
            compSizes.erase(compSizes.find(size2));
 
            // Perform the merge operation
            merge(edge.first, edge.second);
 
            // Insert the combined size
            compSizes.insert(size1 + size2);
        }
 
        // Maximum value in the multiset is
        // the max component size
        answer.push_back(*compSizes.rbegin());
    }
 
    // Printing the answer
    for (int i = 0; i < answer.size(); i++) {
        cout << answer[i] << " ";
    }
}
 
// Driver code
int main()
{
    int N = 4;
    vector > E;
    E.push_back(make_pair(1, 2));
    E.push_back(make_pair(3, 4));
    E.push_back(make_pair(2, 3));
 
    maxSize(E, N);
 
    return 0;
}
输出:
2 2 4

时间复杂度: O(|E| * log(N))
辅助空间: O(N)