给定数组arr [] [] ,其中包含要用于构造具有N个节点的无向图G的图的边缘,则任务是在构造图时添加每个边后,在图中找到最大的组件尺寸。
例子:
Input: N = 4, arr[][] = {{1, 2}, {3, 4}, {2, 3}}
Output: 2 2 4
Explanation:
Initially, the graph has 4 individual nodes 1, 2, 3 and 4.
After the first edge is added : 1 – 2, 3, 4 -> maximum component size = 2
After the second edge is added : 1 – 2, 3 – 4 -> maximum component size = 2
After the third edge is added : 1 – 2 – 3 – 4 -> maximum component size = 4
Input: N = 4, arr[][] = {{2, 3}, {1, 2}, {1, 5}, {2, 4}}
Output: 2 3 4 5
幼稚的方法:针对此问题的幼稚的方法是依次添加边缘,并在每一步应用深度优先搜索算法来找到最大成分的大小。
下面是上述方法的实现:
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))