1955 - plimbare1

De la Universitas MediaWiki
Versiunea din 4 iunie 2024 01:32, autor: Danciu (discuție | contribuții) (Pagină nouă: = Cerința = Personajul acestei probleme este Lucian. Lucian locuiește în tara lui Verde Împărat, această tară având <code>n</code> orașe, numerotate de la <code>1</code> la <code>n</code>. Cum în orice poveste cu împărați există și o prințesă, și în problema noastră avem o prințesă, să o numim Maria. Maria este fiica lui Verde Împărat și în același timp prietena lui Lucian. În tara lui Verde Împărat se apropie sărbătorile, iar ca să fie sig...)
(dif) ← Versiunea anterioară | Versiunea curentă (dif) | Versiunea următoare → (dif)

Cerința

Personajul acestei probleme este Lucian. Lucian locuiește în tara lui Verde Împărat, această tară având n orașe, numerotate de la 1 la n. Cum în orice poveste cu împărați există și o prințesă, și în problema noastră avem o prințesă, să o numim Maria. Maria este fiica lui Verde Împărat și în același timp prietena lui Lucian.

În tara lui Verde Împărat se apropie sărbătorile, iar ca să fie sigur de un nou mandat, împăratul a promis că va repara câteva drumuri, astfel încât să se poată ajunge din orice oraș, în oricare alt oraș, mergând doar pe drumuri care nu sunt stricate. Fiecare drum care este stricat are un cost de reparație , și având în vedere că se apropie sărbătorile, Împăratul ar vrea să repare drumurile optim, astfel încât să obțină un cost cât mai mic. Știind că Lucian vrea să-i ceară mâna Mariei, Împăratul i-a încredințat lui Lucian această sarcină, iar în cazul în care nu va putea să o îndeplinească îl va izgoni din tară. Lucian nu a fost prezent mai deloc la orele de algoritmică din liceu și vă cere vouă ajutorul pentru această problema complicată. Având la dispoziție lista drumurilor, precum și lista drumurilor stricate, voi trebuie să-i spuneți lui Lucian care este suma minimă pe care trebuie să o folosească pentru a se putea ajunge din orice oraș în oricare alt oraș.

Date de intrare

Fișierul plimbare1.in conține pe prima linie două numere N și M, reprezentând numărul de orașe și numărul de drumuri din tara lui Verde Împărat. Pe următoarele M linii vor fi descrise drumurile sub următoarea formă:

  • 1 a b – există un drum între a și b;
  • 2 a b c – există un drum între a și b care poate fi reparat cu costul c.

Date de ieșire

Fișierul plimbare1.out conține pe prima linie un număr S, reprezentând costul minim al reparării drumurilor, pentru a se putea ajunge din orice oraș în oricare alt oraș.

Restricții și precizări

1 ≤ N ≤ 100.000

1 ≤ M ≤ 120.000

1 ≤ c ≤ 250 – număr natural

• drumurile sunt bidirecționale

Exemplu:

plimbare1.in

5 5
1 1 2 
1 3 4
2 2 3 6
2 3 5 9
2 4 5 6

plimbare1.out

12

Explicație

Observăm că nu putem ajunge în orașul 3 din orașul 1, sau din orașul 2 în orașul 3, de aceea trebuie să reparăm un drum, astfel încât să fie posibil să ajungem în orașul 3. Astfel, selectam drumul 2 3 cu costul 6. După ce am reparat acest drum observăm că nu putem ajunge în orașul 5. Avem două drumuri posibile de reparat pentru a ajunge apoi în orașul 5 , 3 5 cu costul 9 si 4 5 cu costul 6. Îl vom alege pe cel mai mic (cel cu costul 6), astfel după ce reparăm și acest drum putem ajunge din orice oraș în oricare altul.

Rezolvare

Inf = float('inf')

def init(n):
    return list(range(n + 1))

def find(x, T):
    if x != T[x]:
        T[x] = find(T[x], T)
    return T[x]

def union(a, b, T):
    T[find(a, T)] = find(b, T)

def kruskal(G, n):
    rez = 0
    T = init(n)
    afis = []
    for x, y, z in G:
        r1 = find(x, T)
        r2 = find(y, T)
        if r1 != r2:
            rez += z
            afis.append((x, y))
            union(r1, r2, T)
    return rez

if __name__ == "__main__":
    with open("plimbare1.in", 'r') as fin, open("plimbare1.out", 'w') as fout:
        n, m = map(int, fin.readline().split())
        G = []
        for _ in range(m):
            line = list(map(int, fin.readline().split()))
            op = line[0]
            if op == 1:
                x, y = line[1:3]
                G.append((x, y, 0))
            else:
                x, y, w = line[1:4]
                G.append((x, y, w))
        G.sort(key=lambda x: x[2])
        rez = kruskal(G, n)
        fout.write(str(rez) + '\n')