Social Network (Codeforces 1609D)
Tags: Greedy, dsu

  William arrived at a conference dedicated to cryptocurrencies. Networking, meeting new people, and using friends' connections are essential to stay up to date with the latest news from the world of cryptocurrencies.The conference has $$$n$$$ participants, who are initially unfamiliar with each other. William can introduce any two people, $$$a$$$ and $$$b$$$, who were not familiar before, to each other. William has $$$d$$$ conditions, $$$i$$$'th of which requires person $$$x_i$$$ to have a connection to person $$$y_i$$$. Formally, two people $$$x$$$ and $$$y$$$ have a connection if there is such a chain $$$p_1=x, p_2, p_3, \dots, p_k=y$$$ for which for all $$$i$$$ from $$$1$$$ to $$$k - 1$$$ it's true that two people with numbers $$$p_i$$$ and $$$p_{i + 1}$$$ know each other.For every $$$i$$$ ($$$1 \le i \le d$$$) William wants you to calculate the maximal number of acquaintances one person can have, assuming that William satisfied all conditions from $$$1$$$ and up to and including $$$i$$$ and performed exactly $$$i$$$ introductions. The conditions are being checked after William performed $$$i$$$ introductions. The answer for each $$$i$$$ must be calculated independently. It means that when you compute an answer for $$$i$$$, you should assume that no two people have been introduced to each other yet.

Input: The first line contains two integers $$$n$$$ and $$$d$$$ ($$$2 \le n \le 10^3, 1 \le d \le n - 1$$$), the number of people, and number of conditions, respectively.Each of the next $$$d$$$ lines each contain two integers $$$x_i$$$ and $$$y_i$$$ ($$$1 \le x_i, y_i \le n, x_i \neq y_i$$$), the numbers of people which must have a connection according to condition $$$i$$$.

Output: Output $$$d$$$ integers. $$$i$$$th number must equal the number of acquaintances the person with the maximal possible acquaintances will have, if William performed $$$i$$$ introductions and satisfied the first $$$i$$$ conditions.

Note: The explanation for the first test case:In this explanation, the circles and the numbers in them denote a person with the corresponding number. The line denotes that William introduced two connected people. The person marked with red has the most acquaintances. These are not the only correct ways to introduce people.  

Sample Inputs:
7 6
1 2
3 4
2 4
7 6
6 5
1 7

10 8
1 2
2 3
3 4
1 4
6 7
8 9
8 10
1 4

Sample Outputs:
1
1
3
3
3
6

1
2
3
4
5
5
6
8

Solution (Python):
import heapq

class DSU:

    def __init__(self, n):
        self.uf = {i: i for i in range(n)}
        self.rank = {i: 1 for i in range(n)}
        self.h = [(-1, i) for i in range(n)]

    def find(self, x):
        if self.uf[x] != x:
            self.uf[x] = self.find(self.uf[x])
        return self.uf[x]

    def union(self, x, y):
        (px, py) = (self.find(x), self.find(y))
        if px != py:
            if self.rank[px] > self.rank[py]:
                (px, py) = (py, px)
            self.rank[py] += self.rank[px]
            del self.rank[px]
            self.uf[px] = py
            return 0
        return 1
(n, d) = map(int, input().split())
dsu = DSU(n + 1)
rem = 0
for _ in range(d):
    (xi, yi) = map(int, input().split())
    rem += dsu.union(xi, yi)
    ai = list(dsu.rank.values())
    ai.sort(reverse=True)
    print(sum(ai[:min(len(ai), rem + 1)]) - 1)

Solution (Python):
from sys import stdin, stdout
import os
dbg = os.getenv('DEBUG')

class Dsu:

    def __init__(self, n: int) -> None:
        self.parents = list(range(n))
        self.sizes = [1] * n

    def find(self, x: int) -> int:
        if self.parents[x] == x:
            return x
        self.parents[x] = self.find(self.parents[x])
        return self.parents[x]

    def merge(self, x: int, y: int) -> None:
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if self.sizes[x] > self.sizes[y]:
            (x, y) = (y, x)
        self.parents[x] = y
        self.sizes[y] += self.sizes[x]
        self.sizes[x] = 0

def main() -> None:
    (n, d) = map(int, stdin.readline().split())
    dsu = Dsu(n)
    num_components = n
    for i in range(d):
        (x, y) = map(int, stdin.readline().split())
        x -= 1
        y -= 1
        x = dsu.find(x)
        y = dsu.find(y)
        if x != y:
            dsu.merge(x, y)
            num_components -= 1
        num_edges = i + 1
        num_edges_base = n - num_components
        num_edges_left = num_edges - num_edges_base
        if dbg:
            print(f'dsu.sizes = {dsu.sizes!r}')
            print(f'num_edges = {num_edges!r}, num_edges_base = {num_edges_base!r}, num_edges_left = {num_edges_left!r}')
        answer = sum(sorted(dsu.sizes)[-num_edges_left - 1:]) - 1
        stdout.write(f'{answer}\n')
if __name__ == '__main__':
    main()
''

Solution (Python):
(n, d) = map(int, input().split())
p = [-1] * (n + 1)
c = 0

def find(x):
    if p[x] < 0:
        return x
    return find(p[x])
for i in range(d):
    (x, y) = map(int, input().split())
    if find(x) == find(y):
        c += 1
    else:
        p[find(x)] += p[find(y)]
        p[find(y)] = find(x)
    a = sorted(p)
    ans = 0
    for j in range(c + 1):
        ans += a[j]
    print(-(1 + ans))