📜  在将每个边添加到图形后找到最大组件尺寸

📅  最后修改于: 2021-05-04 08:50:34             🧑  作者: 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)

高效方法:想法是使用不交集(按等级和路径压缩的并集)概念来更有效地解决问题。

  • 最初,每个节点在其内部都是不相交的集合。随着边缘的添加,不相交的集合将合并在一起,从而形成更大的分量。在不相交集合的实现中,我们将基于组件大小创建排名系统,即,当两个组件合并时,较大组件的根将被视为合并操作之后的最终根。
  • 在每个边添加后找到最大大小分量的一种方法是遍历大小数组(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))