4290 - Gaseste Ciclu
De la Universitas MediaWiki
Cerinţa
Gigel are un graf cu n noduri și m muchii, care nu este conex. El dorește să afle răspunsul la două întrebări:
1) Care este numărul minim de muchii ce trebuie ađugate astfel încât graful să devină conex?
2) Dacă costul adăugării unei muchii între nodurile a și b este a + b, care este costul total minim al muchiilor care trebuie adăugate astfel încât graful să devină conex?
Date de intrare
Fișierul de intrare unirein.txt conține pe prima linie numerele n și m, pe a doua linie conține numărul c, reprezentând numărul cerinței 1 ⩽ c ⩽ 2, iar pe următoarele m linii se află muchiile grafului a b, 1 ⩽ a, b ⩽ n, a ≠ b.
Date de ieșire
Fișierul de ieșire unireout.txt va conține pe prima linie numărul S, reprezentând răspunsul cerut de Gigel.
Restricţii şi precizări
- 1 ⩽ n ⩽ 100000, 0 ⩽ m ⩽ n-1
- Pentru teste în valoare de 30 de puncte, cerința va fi 1.
- Pentru teste în valoare de 40 de puncte, 1 ⩽ n ⩽ 1000.
Exemplul 1
- unirein.txt
6 3 1 1 2 3 4 5 6
- unireout.txt
Datele de intrare corespund restrictiilor impuse 2
Exemplul 2
- unirein.txt
100001 1 1 1 2
- unireout.txt
Datele de intrare nu corespund restrictiilor impuse
Rezolvare
import heapq
def find(parent, i):
if parent[i] == i:
return i
return find(parent, parent[i])
def union(parent, rank, x, y):
xroot = find(parent, x)
yroot = find(parent, y)
if rank[xroot] < rank[yroot]:
parent[xroot] = yroot
elif rank[xroot] > rank[yroot]:
parent[yroot] = xroot
else:
parent[yroot] = xroot
rank[xroot] += 1
def solve(n, c, edges):
parent = [i for i in range(n+1)]
rank = [0] * (n+1)
for a, b in edges:
union(parent, rank, a, b)
sets = [find(parent, i) for i in range(1, n+1)]
unique_sets = list(set(sets))
if c == 1:
return len(unique_sets) - 1
else:
costs = [i for i in unique_sets]
heapq.heapify(costs)
total_cost = 0
while len(costs) > 1:
cost1 = heapq.heappop(costs)
cost2 = heapq.heappop(costs)
total_cost += cost1 + cost2
heapq.heappush(costs, cost1 + cost2)
return total_cost
def main():
with open('unirein.txt', 'r') as f:
n, _ = map(int, f.readline().split())
c = int(f.readline())
edges = [list(map(int, line.split())) for line in f]
if not (1 <= n <= 100000):
print("Datele de intrare nu corespund restrictiilor impuse")
return
result = solve(n, c, edges)
with open('unireout.txt', 'w') as f:
f.write(str(result))
print("Datele de intrare corespund restrictiilor impuse")
if __name__ == "__main__":
main()
Explicaţie
Se vor uni nodurile 1 și 3, respectiv nodurile 1și 5, s-au folosit 2 muchii, iar costul total va fi 1 + 3 + 1 + 5 = 10.