3339 – Disjoint1

De la Universitas MediaWiki
Versiunea pentru tipărire nu mai este suportată și poate avea erori de randare. Vă rugăm să vă actualizați bookmarkurile browserului și să folosiți funcția implicită de tipărire a browserului.

Se consideră un graf cu N noduri numerotate de la 1 la N și M operații de trei tipuri:

  • 1 x y – se adaugă în graf muchia (x, y). Dacă muchia există deja, operația nu se efectuează
  • 2 x y – întrebare: nodurile x și y se află sau nu în aceeași componentă conexă?
  • 3 – întrebare: care este numărul maxim de noduri dintr-o componentă conexă?

Cerința

Trebuie să răspundeți la toate întrebările de tip 2 și 3.

Date de intrare

Programul citește de la tastatură numerele N și M, iar pe următoarele M linii se află operațiile date fie prin trei valori de forma op x y (pentru operațiile de tip 1 și 2), fie printr-o singură valoare 3 (pentru operațiile de tip 3).

Date de ieșire

Programul va afișa pe ecran, pe câte o linie, răspunsul la fiecare întrebare de tip 2 și 3. Dacă la o întrebare 2 x y răspunsul este afirmativ, adică x și y se află în aceeași componentă conexă, atunci veți afișa DA, iar în caz contrar veți afișa NU.

Restricții și precizări

  • 3 ≤ N ≤ 32.000
  • 3 ≤ M ≤ 300.000
  • va exista cel puțin o operație de fiecare tip.

Exemplul 1

Input:

6 6

1 1 4

1 3 6

2 4 6

1 1 3

2 4 6

3

Output:

NU

DA

4

Exemplul 2

Input:

99999999 6

1 1 4

1 3 6

2 4 6

1 1 3

2 4 6

3

Output:

Invalid input. Please ensure that 3 ≤ N ≤ 32,000 and 3 ≤ M ≤ 300,000.

Rezolvare

def verify_conditions(N, M):
    return 3 <= N <= 32000 and 3 <= M <= 300000

class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n + 1))
        self.rank = [0] * (n + 1)
        self.size = [1] * (n + 1)
        self.max_size = 1

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

    def union(self, x, y):
        root_x = self.find(x)
        root_y = self.find(y)

        if root_x != root_y:
            if self.rank[root_x] < self.rank[root_y]:
                root_x, root_y = root_y, root_x
            self.parent[root_y] = root_x
            self.size[root_x] += self.size[root_y]
            self.max_size = max(self.max_size, self.size[root_x])
            if self.rank[root_x] == self.rank[root_y]:
                self.rank[root_x] += 1

def main():
    N = int(input())
    M = int(input())

    if not verify_conditions(N, M):
        print("Invalid input. Please ensure that 3 ≤ N ≤ 32,000 and 3 ≤ M ≤ 300,000.")
        return

    union_find = UnionFind(N)

    for _ in range(M):
        input_values = input().split()
        operation = int(input_values[0])

        if operation == 1:
            x, y = int(input_values[1]), int(input_values[2])
            union_find.union(x, y)
        elif operation == 2:
            x, y = int(input_values[1]), int(input_values[2])
            result = "DA" if union_find.find(x) == union_find.find(y) else "NU"
            print(result)
        elif operation == 3:
            print(union_find.max_size)

if __name__ == "__main__":
    main()