3338 - disjoint: Diferență între versiuni

De la Universitas MediaWiki
(Pagină nouă: == Cerinţa == Răspundeți la toate întrebările de al doilea tip, în ordinea acestora. == Date de intrare == Programul citește de la tastatură numerele '''N''' și '''M''', iar apoi '''M''' triplete de numere naturale de forma '''op x y''', unde '''op''' poate lua doar valorile 1 și 2, aceste triplete reprezentând câte o operație. == Date de ieşire == Programul va afișa pe ecran, pe câte o linie, răspunsul la fiecare întrebare de tip '''2'''. Dacă la întrebar...)
 
Fără descriere a modificării
Linia 9: Linia 9:
* '''2 ≤ M ≤ 2000'''
* '''2 ≤ M ≤ 2000'''
* va exista cel puțin o operație de tip '''1''' și cel puțin o operație de tip '''2'''.
* va exista cel puțin o operație de tip '''1''' și cel puțin o operație de tip '''2'''.
== Exemplu ==
== Exemplul 1 ==
; Intrare
; Intrare
: 6 6
: 6 6
Linia 19: Linia 19:
: 2 1 6
: 2 1 6
; Ieșire
; Ieșire
: Datele introduse corespund restricțiilor impuse.
: NU
: NU
: DA
: DA
: DA
: DA
== Exemplul 2 ==
; Intrare
: 6 6
: 1 1 4
: 1 3 6
: 2 4 6
: 1 1 3
: 2 4 6
: 2 1 520
; Ieșire
: Datele introduse nu corespund restricțiilor impuse.
== Explicație ==
== Explicație ==
Sunt '''6''' copii și '''6''' operații. După primele două operații, elevii '''1''' și '''4''' sunt în aceeași clasă și '''3''' și '''6''' sunt în aceeași clasă. La întrebarea '''2 4 6''' răspunsul este evident '''NU'''. La a patra operație '''1''' și '''3''' sunt trecuți în aceeași clasă, deci va exista o clasă cu '''4''' copii: '''{1,3,4,6}''', deci la ultimele două întrebări acum răspunsul este '''DA''' la ambele.
Sunt '''6''' copii și '''6''' operații. După primele două operații, elevii '''1''' și '''4''' sunt în aceeași clasă și '''3''' și '''6''' sunt în aceeași clasă. La întrebarea '''2 4 6''' răspunsul este evident '''NU'''. La a patra operație '''1''' și '''3''' sunt trecuți în aceeași clasă, deci va exista o clasă cu '''4''' copii: '''{1,3,4,6}''', deci la ultimele două întrebări acum răspunsul este '''DA''' la ambele.
== Rezolvare ==
== Rezolvare ==
<syntaxhighlight lang="python" line>
<syntaxhighlight lang="python" line>
# Funcția 'find' returnează reprezentantul (sau liderul) al setului în care se află un element dat.
# 3338 - disjoint
def find(parent, i):
def validare(n, m, operati):
     if parent[i] == i:
    # Verificăm dacă N și M sunt în limitele specificate și dacă avem numărul corect de operații
         return i
    if n < 1 or n > 500 or m < 2 or m > 2000 or len(operati) != m:
     return find(parent, parent[i])
        raise ValueError
     tip1 = tip2 = False
    for op, x, y in operati:
        # Verificăm dacă există cel puțin o operație de fiecare tip
        if op == 1:
            tip1 = True
        elif op == 2:
            tip2 = True
        # Verificăm dacă operațiile sunt valide
         if op not in [1, 2] or x < 1 or x > n or y < 1 or y > n:
            raise ValueError
     # Verificăm dacă există cel puțin o operație de fiecare tip
    if not (tip1 and tip2):
        raise ValueError


# Funcția 'union' este utilizată pentru a uni două seturi.
     print("Datele de intrare corespund restrictiilor impuse")
def union(parent, rank, x, y):
     return True
     xroot = find(parent, x)
     yroot = find(parent, y)


    # Atașează arborele mai mic la rădăcina celui mai mare
    if rank[xroot] < rank[yroot]:
        parent[xroot] = yroot
    elif rank[xroot] > rank[yroot]:
        parent[yroot] = xroot
    else :
        parent[yroot] = xroot
        rank[xroot] += 1


# Funcția 'solve' citește datele de intrare și rezolvă problema.
# Funcția 'rezolvare' rezolvă problema dată
def solve():
def rezolvare(n, _, operati):
     N, M = map(int,input().strip().split())
     # Inițializăm părinții și rangurile
     parent = [i for i in range(N+1)]
     parent = [i for i in range(n + 1)]
     rank = [0 for _ in range(N+1)]
     rank = [0 for _ in range(n + 1)]
     res = []
     res = []
      
 
     for _ in range(M):
     # Funcția 'find' găsește reprezentantul unui element
         op, x, y = map(int,input().strip().split())
     def find(i):
         if parent[i] == i:
            return i
        return find(parent[i])
 
    # Funcția 'union' unește două seturi
    def union(x1, y2):
        xroot = find(x1)
        yroot = find(y2)
 
        # Atașăm arborele mai mic la rădăcina celui mai mare
        if rank[xroot] < rank[yroot]:
            parent[xroot] = yroot
        elif rank[xroot] > rank[yroot]:
            parent[yroot] = xroot
        else:
            parent[yroot] = xroot
            rank[xroot] += 1
 
    # Parcurgem operațiile și le aplicăm
    for op, x, y in operati:
         if op == 1:
         if op == 1:
             union(parent, rank, x, y)
             union(x, y)
         else:
         else:
             # Dacă x și y au același părinte (adică sunt în aceeași clasă), atunci afișează 'DA'
             # Dacă x și y au același părinte, atunci sunt în aceeași clasă
             if find(parent, x) == find(parent, y):
             if find(x) == find(y):
                 res.append('DA')
                 res.append('DA')
             else:
             else:
                 res.append('NU')
                 res.append('NU')
      
 
     # Afișăm rezultatele
     print('\n'.join(res))
     print('\n'.join(res))


# Acest cod va fi executat doar dacă scriptul este rulat direct
# Acest cod va fi executat doar dacă scriptul este rulat direct
if __name__ == "__main__":
if __name__ == '__main__':
     solve()
    try:
        # Citim datele de intrare
        N, M = map(int, input().strip().split())
        operatii = [list(map(int, input().strip().split())) for _ in range(M)]
        # Validăm datele de intrare
        validare(N, M, operatii)
        # Rezolvăm problema
        rezolvare(N, M, operatii)
    # Tratăm eventualele erori
     except ValueError:
        print("Datele de intrare nu corespund restrictiilor impuse")


</syntaxhighlight>
</syntaxhighlight>

Versiunea de la data 14 noiembrie 2023 10:16

Cerinţa

Răspundeți la toate întrebările de al doilea tip, în ordinea acestora.

Date de intrare

Programul citește de la tastatură numerele N și M, iar apoi M triplete de numere naturale de forma op x y, unde op poate lua doar valorile 1 și 2, aceste triplete reprezentând câte o operație.

Date de ieşire

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

Restricții și precizări

  • 1 ≤ N ≤ 500
  • 2 ≤ M ≤ 2000
  • va exista cel puțin o operație de tip 1 și cel puțin o operație de tip 2.

Exemplul 1

Intrare
6 6
1 1 4
1 3 6
2 4 6
1 1 3
2 4 6
2 1 6
Ieșire
Datele introduse corespund restricțiilor impuse.
NU
DA
DA

Exemplul 2

Intrare
6 6
1 1 4
1 3 6
2 4 6
1 1 3
2 4 6
2 1 520
Ieșire
Datele introduse nu corespund restricțiilor impuse.

Explicație

Sunt 6 copii și 6 operații. După primele două operații, elevii 1 și 4 sunt în aceeași clasă și 3 și 6 sunt în aceeași clasă. La întrebarea 2 4 6 răspunsul este evident NU. La a patra operație 1 și 3 sunt trecuți în aceeași clasă, deci va exista o clasă cu 4 copii: {1,3,4,6}, deci la ultimele două întrebări acum răspunsul este DA la ambele.

Rezolvare

# 3338 - disjoint
def validare(n, m, operati):
    # Verificăm dacă N și M sunt în limitele specificate și dacă avem numărul corect de operații
    if n < 1 or n > 500 or m < 2 or m > 2000 or len(operati) != m:
        raise ValueError
    tip1 = tip2 = False
    for op, x, y in operati:
        # Verificăm dacă există cel puțin o operație de fiecare tip
        if op == 1:
            tip1 = True
        elif op == 2:
            tip2 = True
        # Verificăm dacă operațiile sunt valide
        if op not in [1, 2] or x < 1 or x > n or y < 1 or y > n:
            raise ValueError
    # Verificăm dacă există cel puțin o operație de fiecare tip
    if not (tip1 and tip2):
        raise ValueError

    print("Datele de intrare corespund restrictiilor impuse")
    return True


# Funcția 'rezolvare' rezolvă problema dată
def rezolvare(n, _, operati):
    # Inițializăm părinții și rangurile
    parent = [i for i in range(n + 1)]
    rank = [0 for _ in range(n + 1)]
    res = []

    # Funcția 'find' găsește reprezentantul unui element
    def find(i):
        if parent[i] == i:
            return i
        return find(parent[i])

    # Funcția 'union' unește două seturi
    def union(x1, y2):
        xroot = find(x1)
        yroot = find(y2)

        # Atașăm arborele mai mic la rădăcina celui mai mare
        if rank[xroot] < rank[yroot]:
            parent[xroot] = yroot
        elif rank[xroot] > rank[yroot]:
            parent[yroot] = xroot
        else:
            parent[yroot] = xroot
            rank[xroot] += 1

    # Parcurgem operațiile și le aplicăm
    for op, x, y in operati:
        if op == 1:
            union(x, y)
        else:
            # Dacă x și y au același părinte, atunci sunt în aceeași clasă
            if find(x) == find(y):
                res.append('DA')
            else:
                res.append('NU')

    # Afișăm rezultatele
    print('\n'.join(res))


# Acest cod va fi executat doar dacă scriptul este rulat direct
if __name__ == '__main__':
    try:
        # Citim datele de intrare
        N, M = map(int, input().strip().split())
        operatii = [list(map(int, input().strip().split())) for _ in range(M)]
        # Validăm datele de intrare
        validare(N, M, operatii)
        # Rezolvăm problema
        rezolvare(N, M, operatii)
    # Tratăm eventualele erori
    except ValueError:
        print("Datele de intrare nu corespund restrictiilor impuse")