4244 - urgenta

From Bitnami MediaWiki

Autorităţile dintr-o zonă de munte intenţionează să stabilească un plan de urgenţă, pentru a reacţiona mai eficient la frecventele calamităţi naturale din zonă. În acest scop au identificat N puncte de interes strategic şi le-au numerotat distinct de la 1 la N. Punctele de interes strategic sunt conectate prin M căi de acces având priorităţi în funcţie de importanţă. Între oricare două puncte de interes strategic există cel mult o cale de acces ce poate fi parcursă în ambele sensuri şi cel puţin un drum (format din una sau mai multe căi de acces) ce le conectează.

În cazul unei calamităţi unele căi de acces pot fi temporar întrerupte şi astfel între anumite puncte de interes nu mai există legătură. Ca urmare pot rezulta mai multe grupuri de puncte în aşa fel încât între oricare două puncte din acelaşi grup să existe măcar un drum şi între oricare două puncte din grupuri diferite să nu existe drum.

Cerința[edit | edit source]

Autorităţile estimează gravitatea unei calamităţi ca fiind suma priorităţilor căilor de acces distruse de aceasta şi doresc să determine un scenariu de gravitate maximă, în care punctele de interes strategic să fie împărţite într-un număr de K grupuri.

Date de intrare[edit | edit source]

Fișierul de intrare urgenta.in are următorul format:

N M K

i1 j1 p1 – între punctele i1 şi j1 există o cale de acces de prioritate p1.

i2 j2 p2 – între punctele i2 şi j2 există o cale de acces de prioritate p2.

iM jM pM – între punctele iM şi jM există o cale de acces de prioritate pM.

Date de ieșire[edit | edit source]

Fișierul de ieșire urgenta.out va avea următorul format:

gravmax – gravitatea maximă

C – numărul de căi de acces întrerupte de calamitate

k1 h1 – între punctele k1 şi h1 a fost întreruptă calea de acces

k2 h2 – între punctele k2 şi h2 a fost întreruptă calea de acces

kC hC – între punctele kC şi hC a fost întreruptă calea de acces

Restricții și precizări[edit | edit source]

  • 0 < N < 256
  • N - 2 < M < 32385
  • 0 < K < N + 1
  • Priorităţile căilor de acces sunt întregi strict pozitivi mai mici decât 256.
  • Un grup de puncte poate conţine între 1 şi N puncte inclusiv.
  • Dacă există mai multe soluţii, programul va determina una singură.

Exemplu:[edit | edit source]

urgenta.in

7 11 4
1 2 1
1 3 2
1 7 3
2 4 3
3 4 2
3 5 1
3 6 1
3 7 5
4 5 5
5 6 4
6 7 3

urgenta.out

27
8
1 3
1 7
2 4
3 4
3 7
4 5
5 6
6 7

Rezolvare[edit | edit source]

<syntaxhighlight lang="python3"> class UnionFind:

   def __init__(self, n):
       self.parent = [i for i in range(n + 1)]
       self.rank = [0] * (n + 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]:
               self.parent[root_y] = root_x
           elif self.rank[root_x] < self.rank[root_y]:
               self.parent[root_x] = root_y
           else:
               self.parent[root_y] = root_x
               self.rank[root_x] += 1


def main():

   nMAX = 255
   fin = open("urgenta.in", "r")
   fout = open("urgenta.out", "w")
   n, m, k = map(int, fin.readline().split())
   edges = []
   edges_fol = [False] * (m + 1)
   tat = [0] * (nMAX + 1)
   niv = [0] * (nMAX + 1)
   grupe, edgfol = n, 0
   costall, costfol = 0, 0
   for _ in range(m):
       a, b, c = map(int, fin.readline().split())
       costall += c
       edges.append((c, a, b))
   edges.sort()
   def rad(nod):
       if tat[nod]:
           return rad(tat[nod])
       return nod
   def changeDads(nod, newdad):
       if tat[nod]:
           changeDads(tat[nod], newdad)
       tat[nod] = newdad
   for i in range(m):
       if grupe == k:
           break
       c, a, b = edges[i]
       rada = rad(a)
       radb = rad(b)
       if rada != radb:
           if niv[rada] < niv[radb]:
               changeDads(a, radb)
           elif niv[rada] > niv[radb]:
               changeDads(b, rada)
           else:
               niv[rada] += 1
               changeDads(b, rada)
           
           edges_fol[i] = True
           edgfol += 1
           costfol += c
           grupe -= 1
   fout.write(str(costall - costfol) + '\n')
   fout.write(str(m - edgfol) + '\n')
   for i in range(m):
       if not edges_fol[i]:
           fout.write(str(edges[i][1]) + ' ' + str(edges[i][2]) + '\n')
   fin.close()
   fout.close()


if __name__ == "__main__":

   main()

</syntaxhighlight>