350 likes | 486 Views
Dýpt-fyrst leitun (DFS). Greining reiknirita vor 2002. Yfirlit. Almennt um net DFS leitun DFS: Skapalón Tímasetningar, flokkun hnúta/stika Tengdir þættir Tvítengdir þættir. Dæmi um net. Tölvunet, nærnet, víðnet, Internet Vensl xRy (x,y) E Rafrás Forgangur verkefna
E N D
Dýpt-fyrst leitun (DFS) Greining reiknirita vor 2002
Yfirlit • Almennt um net • DFS leitun • DFS: Skapalón • Tímasetningar, flokkun hnúta/stika • Tengdir þættir • Tvítengdir þættir
Dæmi um net • Tölvunet, nærnet, víðnet, Internet • Vensl xRy (x,y) E • Rafrás • Forgangur verkefna • Stöður í skák • Flug milli staða og tímalengd • Tengslanet
12-flötungur Möskvi Ýmis net
Kortalitun • Kortagerðamenn til forna sáu að 4 litir virðast alltaf duga.
Ritháttur • Hnútur (node, vertex) • Leggur, stika (edge) • Leið (path) • Rás (cycle) • Þáttur (connected component)
Dýpt-fyrst leitun • Aðferð til að komast í gegnum völundarhús án minnis. • Förum eins langt og við komumst, án þess að fara á sama stað tvisvar. • Þegar það er ekki hægt lengum, bökkum við.
D A B G F E C
Hnútar litaðir Hvít-Grá-Svart • Hvítur: Ekki enn heimsóttur • Grár: Heimsóttur, en ekki kvaddur • Á stafla • Svartur: Heimsóttur og kvaddur Tímapúls fyrir hverja heimsókn og kveðju • Komutími og kveðjutími hnúts
DFS skapalón • int dfs(node v) • litur[v] = grár; aðrirgrannar = grannar[v] • <Forvinnsla á hnút v> • for each neighbor w of v do • if (litur[w] == hvítur) • <Byrjunarvinnsla með tréstiku vw> • int w_skil = dfs(w, ...) • <Endavinnsla á tréstiku vw (m w_skil)> • else • <Vinnsla með fram/bak/kross-stiku vw> • <Eftirvinnsla á hnút v (þ.m.t. útreikningur á skil)> • litur[v] = svartur; return skil
int dfsSweep(G) • <Núllstillum fylki litur með gildinu hvítur> • fyrir hvern hnút v í G gerðu • if (litur[v] == hvítur) • int vSkilagildi = dfs(v) • <Meðhöndla vSkilagildi> • Return skil
int dfs(IntList[] grannar, int[] litur, int v, ...) • litur[v] = grár; aðrirgrannar = grannar[v] • <Forvinnsla á hnút v> • while (aðrirgrannar != nil) • w = first(aðrirgrannar); • if (litur[w] == hvítur) • <Byrjunarvinnsla með tréstiku vw> • int w_skilagildi = dfs(grannar, litur, w,...) • <Endavinnsla á tréstiku vw (sem notar w_skilagildi)> • else • <Vinnsla með fram/bak/kross-stiku vw> • aðrirgrannar = rest(aðrirgrannar) • <Eftirvinnsla á hnút v (þ.m.t. útreikningur á skilagildi)> • litur[v] = svartur; return skilagildi
Tímaflækja • Aðgerðir í dfsSweep() kosta O(n) • Kallað er á dfs(v) einu sinni fyrir hvern hnút • v er hvítur í byrjun, og strax litaður grár • Þarmeð eru aðgerðir 1-3 og 12-13 • Aðgerðir 4-11 framkvæmdar O(m) sinnum • Einu sinni fyrir hvern granna hnúts v • vV d(v) = 2m • Samtals O(n+m)
Kafli: Tengdir þættir • Fyrsta spurning varðandi net er kannski“Er netið samhangandi?”“Er hægt að komast frá hvaða hnút sem er í hvaða annan hnút sem er?” • Þegar svarið er nei, þá viljum við finna þá hluta netsins sem eru samhangandi; slíkir hlutar kallast tengdir þættir (connected components)
int TengdirÞættir(IntList grannar, int n, int[] þáttur) int[]litur=new int[n+1]; int v, þáttno; <Núllstillum litur með gildinu hvítur> þáttno=1 for (int v=1; v <= n; v++) if (litur[v] == hvítur) ccDFS(grannar, litur, v, þáttno, þáttur) þáttno++ return
void ccDFS(IntList[] grannar, int[] litur, int v, int þáttnúmer, int[] þáttur) • litur[v] = grár; aðrirgrannar = grannar[v] • <Forvinnsla á hnút v>: þáttur[v] = þáttnúmer • while (aðrirgrannar != nil) • w = first(aðrirgrannar); • if (litur[w] == hvítur) • <Byrjunarvinnsla með tréstiku vw> • ccDFS(grannar, litur, w, þáttnúmer, þáttur) • <Endavinnsla á tréstiku vw> • else • <Vinnsla með fram/bak/kross-stiku vw> • aðrirgrannar = rest(aðrirgrannar) • <Eftirvinnsla á hnút v> • litur[v] = svartur; return
1 2 5 8 8 7 3 4 6
boolean órásaðDFS(IntList[] grannar, int[] litur, int v) • litur[v] = grár; aðrirgrannar = grannar[v]; • rás = FALSE • while (aðrirgrannar != nil) • w = first(aðrirgrannar); • if (litur[w] == hvítur) • órásaðDFS(grannar, litur, w) • else if (litur[w] == grár) • rás = TRUE • aðrirgrannar = rest(aðrirgrannar) • litur[v] = svartur; return rás
Global: int topoNo = 0; int[] topo; Úttak: Topsort röðun á hnútum í DAG, gefið í topo[v]. • void topoDFS(IntList[] grannar, int[] litur, int v) • litur[v] = grár; aðrirgrannar = grannar[v] • while (aðrirgrannar != nil) • w = first(aðrirgrannar); • if (litur[w] == hvítur) • topoDFS(grannar, litur, w) • aðrirgrannar = rest(aðrirgrannar) • topoNo++; topo[v] = topoNo • litur[v] = svartur; return
Tímasetningar í DFS • dfs(node v) • litur[v] = grár; • tími++; komutími[v] = time • for each neighbor w of v do • if (litur[w] == hvítur) • foreldri[w] = v // Foreldrastika í DFStré • dfs(w) • tími++; brottfarartími[v] = time • litur[v] = svartur; return
5/6 1 /10 D A 12/13 2 /7 G B F 8/9 E C 11 /14 3/4
Líftímar hnúta A B C D E F G H 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Líftímar hnúta • Líftími[v] = [komutími[v], brottfarartími[v]] • Ef v er forfaðir w, þá er inniheldur líftími[v] líftíma w. • Ef hvorugur er forfaðir hins, þá skarast líftímarnir ekki.
Flokkun stika vw er.... • bakstika, ef litur[w] == grár • tréstika, ef litur[w] == hvítur, • framstika, ef líftími[w] líftími[v] • krossstika, ef líftími w var fyrir komutíma v
4 6 1 2 5 8 7 3
4 6 1 2 5 8 7 3 Skurðhnútar (articulation points)
4 6 1 2 5 8 7 3 Tvítengdir þættir (biconnected components)
4 6 1 2 5 8 7 3 Tvítengdir þættir (biconnected components)
Ef v er skurðhnútur, þá fara allar leiðir frá öðrum endanum yfir á hinn endann í gegnum v • Skoðum undirtré v í DFS-trénu: • Engar leiðir liggja frá niðjum v til forfeðra v. • Engar stikur liggja frá niðjum v til forfeðra v. • = Engar bakstikur frá niðjum v ná upp fyrir v. • Höldum utan um: • Hversu hátt í trénu má komast frá viðkomandi hnút • Metum sem lægstann komutíma
Int tvítengtDFS(v) // Skilar hæsta hnút sem v kemst í • litur[v] = grár; • tími++; komutími[v] = time • for each neighbor w of v do • if (w hefur ekki verið heimsóttur) • wbak = tvítengtDFS(w) • if (wbak >= komutími[v]) • {Skila nýjum tvítengdum þætti með hluttré • með rótina w og aðlægar stikur, fyrir utan • það sem þegar hefur verið skilað.} • bak = min(bak, wbak) • else if (vw er bakstika) • bak = min(komutími[w], bak) • litur[v] = svartur; return bak
Int tvítengtDFS(v) // Skilar hæsta hnút sem v kemst í • litur[v] = grár; tími++; bak = komutími[v] = time • for each neighbor w of v do • if (litur[w] == hvítur) • push(stikuStafli, vw) • wbak = tvítengtDFS(w) • if (wbak >= komutími[v]) • Skilum nýjum tvítengdum þætti, með því • að poppa af stikuStafla til og með vw • bak = min(bak, wbak) • else if (litur[w]=grár and w <> foreldri(v)) • push(stikuStafli, vw) • bak = min(komutími[w], bak) • litur[v] = svartur; return bak