先决条件:
- 不相交集数据结构
- 放
- Unordered_Map
不相交集数据结构用于跟踪一组元素,这些元素被划分为多个不相交(不重叠)的子集。
在本文中,我们将学习动态构建相同的数据结构。这种数据结构基本上可以解决以下情况:由于顺序10 9的大量输入而导致我们不能简单地使用数组来创建不相交集的情况。
为了说明这一点,请考虑以下问题。当顶点总数最多可以达到10 ^ 9时,我们需要在图中找到连接的组件总数。
例子:
Input : Edges : { { 1, 2 },
{ 2, 3 },
{ 4, 5 } }
Output : 2
Explanation: {1, 2, 3} forms a component and
{4, 5} forms another component.
解决此问题的想法是,我们将维护两个哈希表(在C++中使用unordered_maps实现)。一个为父母而其他为学位。 Parent [V]将给出顶点V所属于的组件的父对象,而Degree将给出该组件中的顶点数。
最初,“父级”和“学位”都将为空。我们将继续按顺序向地图插入顶点。
同时查看代码和说明以更好地理解。下面是代码中用于解决上述问题的方法:
- getParent(V):此方法将给定顶点V的父级。在这里,我们递归地找到顶点V的父级(请参见代码),与此同时,我们将该组件中的所有顶点分配为具有相同的父级。数据结构,同一组件中的所有顶点都具有相同的父对象。)
- Union():当我们添加一条边并且两个顶点属于不同的组件时,我们调用Union()方法来将这两个组件连接在一起。此处,将两个组件连接在一起后形成的组件的父对象将是在联合之前具有更多顶点数量的两个组件中的组件的父对象。新组件的程度将相应更新。
- getTotalComponent():同一组件中的顶点将具有相同的父对象。
我们使用unordered_set(STL)来计算组件总数。由于我们将数据结构保持为动态,因此可以有任何未添加到任何组件的顶点,因此它们是单独的不同组件。因此,组件总数将由下式给出:Total no of Component = Total Vertices - Number of Vertices in parent (Map) + Number of Component formed from the Vertexes inserted in the graph.
下面是上述想法的实现:
C++
// Dynamic Disjoint Set Data Structure
// Union-Find
#include
using namespace std;
int N;
int Edges[3][2];
// Dynamic Disjoint Set Data Structure
struct DynamicDisjointSetDS {
// We will add the vertex to the edge
// only when it is asked to i.e. maintain
// a dynamic DS.
unordered_map parent, degree;
// Total nomber of Vertex in the Graph
int N;
// Constructor
DynamicDisjointSetDS(int n)
{
N = n;
}
// Get Parent of vertex V
int getParent(int vertex)
{
// If the vertex is already inserted
// in the graph
if (parent.find(vertex) != parent.end()) {
if (parent[vertex] != vertex) {
parent[vertex] =
getParent(parent[vertex]);
return parent[vertex];
}
}
// if the vertex is operated for the first
// time
else {
// insert the vertex and assign its
// parent to itself
parent.insert(make_pair(vertex, vertex));
// Degree of the vertex
degree.insert(make_pair(vertex, 1));
}
return vertex;
}
// Union by Rank
void Union(int vertexA, int vertexB)
{
// Parent of Vertex A
int x = getParent(vertexA);
// Parent of Vertex B
int y = getParent(vertexB);
// if both have same parent
// Do Nothing
if (x == y)
return;
// Merging the componet
// Assigning the parent of smaller Component
// as the parent of the bigger Component.
if (degree[x] > degree[y]) {
parent[y] = x;
degree[x] = degree[x] + degree[y];
}
else {
parent[x] = y;
degree[y] = degree[y] + degree[x];
}
}
// Count total Component in the Graph
int GetTotalComponent()
{
// To count the total Component formed
// from the inserted vertex in the Graph
unordered_set total;
// Iterate through the parent
for (auto itr = parent.begin();
itr != parent.end(); itr++) {
// Add the parent of each Vertex
// to the set
total.insert(getParent(itr->first));
}
// Total Component = Total Vertexes -
// Number of Vertex in the parent +
// Number of Component formed from
// the Vertexes inserted in the Graph
return N - parent.size() + total.size();
}
};
// Solve
void Solve()
{
// Declaring the Dynamic Disjoint Set DS
DynamicDisjointSetDS dsu(N);
// Traversing through the Edges
for (int i = 0; i < 3; i++) {
// If the Vertexes in the Edges
// have same parent do nothing
if (dsu.getParent(Edges[i][0]) ==
dsu.getParent(Edges[i][1])) {
continue;
}
// else Do Union of both the Components.
else {
dsu.Union(Edges[i][0], Edges[i][1]);
}
}
// Get total Components
cout << dsu.GetTotalComponent();
}
// Driver Code
int main()
{
// Total Number of Vertexes
N = 5;
/* Edges
* 1 <--> 2
* 2 <--> 3
* 4 <--> 5 */
Edges[0][0] = 1;
Edges[0][1] = 2;
Edges[1][0] = 2;
Edges[1][1] = 3;
Edges[2][0] = 4;
Edges[2][1] = 3;
// Solve
Solve();
return 0;
}
Python3
# Dynamic Disjoint Set Data Structure
# Union-Find
# Dynamic Disjoint Set Data Structure
class DynamicDisjointSetDS:
# Constructor
def __init__(self, n):
# Total nomber of Vertex in the Graph
self.N = n
# We will add the vertex to the edge
# only when it is asked to i.e. maintain
# a dynamic DS.
self.parent = {}
self.degree = {}
# Get Parent of vertex V
def getParent(self, vertex):
# If the vertex is already inserted
# in the graph
if vertex in self.parent:
if self.parent[vertex] != vertex:
self.parent[vertex] = \
self.getParent(self.parent[vertex])
return self.parent[vertex]
# if the vertex is operated
# for the first time
else:
# insert the vertex and assign
# its parent to itself
self.parent[vertex] = vertex
# Degree of the vertex
self.degree[vertex] = 1
return vertex
# Union by Rank
def Union(self, vertexA, vertexB):
# Parent of Vertex A
x = self.getParent(vertexA)
# Parent of Vertex B
y = self.getParent(vertexB)
# if both have same parent
# Do Nothing
if x == y:
return
# Merging the componet
# Assigning the parent of smaller Component
# as the parent of the bigger Component.
if self.degree[x] > self.degree[y]:
self.parent[y] = x
self.degree[x] = (self.degree[x] +
self.degree[y])
else:
self.parent[x] = y
self.degree[y] = (self.degree[y] +
self.degree[x])
# Count total Component in the Graph
def GetTotalComponent(self):
# To count the total Component formed
# from the inserted vertex in the Graph
total = set()
# Iterate through the parent
for itr in self.parent:
# Add the parent of each Vertex
# to the set
total.add(self.getParent(itr))
# Total Component = Total Vertexes -
# Number of Vertex in the parent +
# Number of Component formed from
# the Vertexes inserted in the Graph
return self.N - len(self.parent) + len(total)
# Solve
def Solve(N):
# Declaring the Dynamic Disjoint Set DS
dsu = DynamicDisjointSetDS(N)
# Traversing through the Edges
for i in range(0, 3):
# If the Vertexes in the Edges
# have same parent do nothing
if (dsu.getParent(Edges[i][0]) ==
dsu.getParent(Edges[i][1])):
continue
# else Do Union of both the Components.
else:
dsu.Union(Edges[i][0], Edges[i][1])
# Get total Components
print(dsu.GetTotalComponent())
# Driver Code
if __name__ == "__main__":
# Total Number of Vertexes
N = 5
Edges = [[1, 2], [2, 3], [4, 3]]
# Solve
Solve(N)
# This code is contributed by
# Rituraj Jain
输出:
2
注意:如果顶点数量更大,我们只需将数据类型从int更改为long long即可实现相同的代码。