Algdat - øvingsforelesning Topologisk sortering og minimale spenntrær Nils Barlaug
Dagens plan 1. 2. 3. 4. 5. Praktisk og dagens plan Topologisk sortering Minimale spenntrær a. Kruskal b. Prim Tips til øving 4 LF øving 3 Det blir Kahoot!, så følg med og ha klar en enhet du kan delta med! For presentasjoner med mer tekst og forklaringer se tidligere års utmerkede presentasjoner
Topologisk sortering
Annet eksempel på topologisk sortering
Enda et eksempel
Enda et eksempel
DAG - Directed Acyclic Graph ( rettet asyklisk graf) Ikke dag DAG DAG
Topologisk sortering Abstraksjon En topologisk sortering av en DAG G er en lineær ordning av nodene i G slik at hvis G inneholder en kant (u, v) kommer u før v i ordningen. (Cormen) Hvordan kan vi løse dette generelt?
Topologisk sortering - algoritmen (i boka) Kjør DFS på alle noder. Når en node er ferdigprosessert legges den først i den topologiske ordningen. La oss prøve algoritmen på denne snedige grafen
Magisk? Hvorfor fungerer det? Vi er i et DFS-søk og akkurat ankommet node u. 1. Hvis node v ikke har blitt oppdaget ennå vil vi besøke og fullføre den før vi fullfører u. Da havner den bak u. 2. Hvis node v allerede er fullført er den lagt til i den topologiske ordningen. Da vil u havne foran. 3. Hvis node v allerede er oppdaget men ikke fullført? Da har vi oppdaget en sykel, og har følgelig ikke med en DAG å gjøre! u v
Kjøretid DFS, men vi gjør en O(1)-operasjon for hver node Altså samme kompleksitet som for DFS Θ(V + E)
Kahoot!
Minimale spenntrær
Annet eksempel
Minimale spenntrær Abstraksjon Spenntre Et utvalg kanter i en (urettet og sammenhengende) graf som danner et tre på en slik måte at alle noder er med i treet. Minimale spenntrær Spenntrær som minimerer summen av kantvekter i treet Hvordan kan vi finne et slikt minimalt spenntre?
Vi gjør det grådig Lokalt optimaliserte valg gir oss en globalt optimal løsning Legge til en og en trygg kant
Teorem 23.1 Snitt
Teorem 23.1 (lett kant trygg kant) Trygg / lett kant (u, v) ---- Kanter vi vet tilhører et minimalt spenntre (A) Et snitt som respekterer A Vanlig kant Lett kant: minimal kant som krysser snittet ----
Teorem 23.1 - bevis-skisse Minimalt spenntre T i en graf Et subset av kantene i T, kalt A Et snitt som respekterer A ---- Lett kant utenfor T ---- A {(u, v)} er subset av et minimalt spenntre Lett kant: minimal kant som krysser snittet
Kruskal Sorter alle kanter etter stigende kantvekt Legg til kanter så lenge de ikke lager en sykel Hvorfor vil dette fungere (i henhold til teorem 23.1)? Kjøretid Implementasjonsavhengig O(E lg V) hvis man bruker disjoint-set forest La oss prøve algoritmen på denne snertne grafen
Prim Start med en tilfeldig node som startnode til treet T Legg hele tiden til billigste kant som utvider treet T med en ny node Hvorfor vil dette fungere (i henhold til teorem 23.1)? Kjøretid Kommer an på hvordan vi lager prioritetskøen Binary heap: O(E lg V) Fibonacci heap: O(E + V lg V) (ikke pensum) La oss prøve algoritmen på denne snodige grafen
Kahoot!
Øving 4 - Prinsessejakt Delgrafen som ikke kan nås fra 1 Delgrafen som ikke kan nås fra 2
Rammeverket from sys import * import traceback def subgraftetthet(nabomatrise, startnode): n = len(nabomatrise) # SKRIV DIN KODE HER if noder == 0: return 0.0 else: return float(kanter) / float(noder**2) try: n = int(stdin.readline()) nabomatrise = [None] * n # rader for i in range(0, n): nabomatrise[i] = [False] * n # kolonner linje = stdin.readline() for j in range(0, n): nabomatrise[i][j] = (linje[j] == '1') for linje in stdin: start = int(linje) print "%.3f" % (subgraftetthet (nabomatrise, start) + 1E-12) except: traceback.print_exc(file=stderr)
Rammeverket - input def subgraftetthet(nabomatrise, startnode): n = len(nabomatrise) # SKRIV DIN KODE HER if noder == 0: return 0.0 else: return float(kanter) / float(noder**2) Spørsmål? Input: 6 011000 000100 000110 000001 010101 000100 1 2 Output: 0.222 0.000
Teoriøving 3 - LF
Praksisøving 3 - Kobra lærer å stave def bygg(ordliste): # START IKKE-UTDELT KODE toppnode = Node() for (ord, posisjon) in ordliste: node = toppnode for bokstav in ord: if not bokstav in node.barn: node.barn[bokstav] = Node() node = node.barn[bokstav] node.posi.append(posisjon) return toppnode # SLUTT IKKE-UTDELT KODE def posisjoner(ord, indeks, node): # START IKKE-UTDELT KODE if indeks >= len(ord): posi = node.posi elif ord[indeks] == "?": posi = [] for barn in node.barn.values(): posi += posisjoner(ord, indeks + 1, barn) elif ord[indeks] in node.barn: posi = posisjoner(ord, indeks + 1, node.barn [ord[indeks]]) else: posi = [] return posi # SLUTT IKKE-UTDELT KODE
Spørsmål?