Disjoint Set Union
Maintain the size of the most populated region after each query.
Solution for the subtask 1 (21 points):
The solution of this subtask is to use breadth first search after applying each query to find all the regions’ city sets. If we have all the regions’ cities sets, we can easily find the maximal populated region.
Let’s describe this approach in more details.
Integer array P, where P[i] is the population of city numbered the ith.
Boolean array D, where D[j] is true, if the road numbered the jth has been destroyed, and false otherwise.
Adjacency list Adj. We can store this list efficiently, for example, using STL vector in C++. For every adjacent node, let’s store a structure, containing the following fields:
- The number of the adjacent node, denoted by node.
- The ID of the corresponding edge, denoted by edge.
Having all this, we can process the queries in the following way:
P x y - change the population of the city numbered the xth to y. In this case, we just make a single assignment: P[x] = y. This operation is performed in O(1).
D x - destroy the road numbered the xth. Again, this is just a single assignment (D[x] = true), so it is also performed in O(1).
Now, how to find the size of the maximal populated region.
We will make use of queue data structure.
Let’s iterate through all the nodes. Whenever we find a node which was not included in any connected component, we start the breadth first search. Let’s describe it in brief:
- Add the first node of the region to the queue.
- While the queue is not empty, pick the node from the head of the queue and add all its’ not yet added neighbors.
Let’s denote Boolean array Used, where Used[i] is true, if ith city was added to queue, and false otherwise.
The pseudocode of the algorithm for finding the size of the most populated region is given below.
ans = 0; For i := 1 to N used[i] = false For i := 1 to N if not used[i] queue.add(i); population = 0; while queue is not empty do curNode = queue.pop(); population += P[curNode]; For j := 0 to Adj[curNode].Length if ((not D[Adj[curNode][j].edge]) and (not Used[Adj[curNode][j].node])) Used[Adj[curNode][j].node] = true; queue.add[Adj[curNode][j].node]; ans = Max(ans, population); return ans
The complexity is O(Q*(N+M)).
Solution for all subtasks:
We will use the data structure called Disjoint Set Union.
Let’s have N elements numbered 1 to N and N sets. Initially, the ith set contains the ith element.
Disjoint Set Union maintains two basic operations:
Uniting two sets.
Finding the set containing the given element.
The amortized time per operation is O(\alpha(N)), where \alpha(N) is less than 5 for all remotely practical values of N.
Note that you don’t have to output the size of the most populated region before reading the next query. So, you can read all the queries in advance and solve the task in reverse order.
Assume that all Q queries were performed. Let’s add all connected components (regions) to the DSU. Obviously, we can determine the most populated region.
Let’s create the DSU with N elements denoting the cities and N sets denoting the regions. Along with each set (say, the Xth), let’s maintain the value of P[X], denoting the total population of the cities in the Xth set. Now, the DSU corresponds to the road system with N cities, given populations and without roads. Note that we should take the populations that are obtained after the performing of all the queries.
Now, assume that all the queries has already been performed. Then, there is a set of roads, which has not been deleted. Let’s add all of them. The addition of the road is simply merging two corresponding sets in the DSU structure. Since we have one non-standard operation here, namely, handling the sizes of the regions, letТs give a pseudocode for it.
Given that we need to add a road connecting the city numbered the Xth and the city numbered the Yth.
Merge (X, Y) setX = FindSet(X) setY = FindSet(Y) if (setX == setY) return; SetParent(setY, setX) P[setX] = P[setX] + P[setY]
Now, let’s “rollback” the queries starting with the last one. The “rollback” of the change population query is changing the value of the corresponding P[X], and the “rollback” of the road deletion query is adding the road like we’ve described above.
Meanwhile, we can also maintain a priority queue of an STL set for determining the size of the largest region quickly. This way, we can answer on the maximal region population in O(\log N).
The complexity is O(N + M \alpha(N) + Q \log N).
Can be found here
Can be found here