/// <summary> /// Wyznacza silnie spójne składowe /// </summary> /// <param name="g">Badany graf</param> /// <param name="scc">Silnie spójne składowe (parametr wyjściowy)</param> /// <returns>Liczba silnie spójnych składowych</returns> /// <remarks> /// scc[v] = numer silnie spójnej składowej do której należy wierzchołek v<br/> /// (numerujemy od 0)<br/> /// <br/> /// Metoda uruchomiona dla grafu nieskierowanego zgłasza wyjątek <see cref="System.ArgumentException"/>. /// <br/> /// Graf wejściowy pozostaje niezmieniony. /// </remarks> public static int StronglyConnectedComponents(this Graph g, out int[] scc) { scc = new int[g.VerticesCount]; int[] myscc = new int[g.VerticesCount]; if (g.Directed == false) { throw new System.ArgumentException("Graph should be directed"); } Graph tmp = Reverse(g); Stack <int> S = new Stack <int>(g.VerticesCount); Predicate <int> postFix = delegate(int n) { S.Push(n); return(true); }; bool[] added = new bool[g.VerticesCount]; int cc = 0; g.DFSearchAll(null, postFix, out cc, null); cc = 0; Predicate <int> AddToComponent = delegate(int n) { if (added[n]) { return(true); } myscc[n] = cc; added[n] = true; return(true); }; while (S.Count > 0) { int v = S.Pop(); if (added[v]) { continue; } tmp.DFSearchFrom(v, null, AddToComponent, null); cc++; } scc = myscc; return(cc); }
/// <summary> /// Znajduje rozwiązanie przybliżone problemu komiwojażera tworząc cykl Hamiltona na podstawie drzewa rozpinającego /// </summary> /// <param name="g">Badany graf</param> /// <param name="cycle">Znaleziony cykl (parametr wyjściowy)</param> /// <returns>Długość znalezionego cyklu (suma wag krawędzi)</returns> /// <remarks> /// Elementy (krawędzie) umieszczone są w tablicy <i>cycle</i> w kolejności swojego następstwa w znalezionym cyklu Hamiltona.<br/> /// <br/> /// Jeśli algorytm bazujący na drzewie rozpinającym nie znajdzie w badanym grafie cyklu Hamiltona /// (co oczywiście nie znaczy, że taki cykl nie istnieje) to metoda zwraca <b>null</b>, /// parametr wyjściowy <i>cycle</i> również ma wówczas wartość <b>null</b>.<br/> /// <br/> /// Metodę można stosować dla grafów nieskierowanych.<br/> /// Zastosowana do grafu skierowanego zgłasza wyjątek <see cref="System.ArgumentException"/>.<br/> /// <br/> /// Metodę można stosować dla dla grafów z dowolnymi (również ujemnymi) wagami krawędzi.<br/> /// <br/> /// Dla grafu nieskierowanego spełniajacego nierówność trójkąta metoda realizuje algorytm 2-aproksymacyjny. /// </remarks> public static int?TSP_TreeBased(this Graph g, out Edge[] cycle) { // TODO - algorytm oparty na minimalnym drzewie rozpinajacym cycle = null; if (g.Directed == true) { throw new System.ArgumentException(); } // Niespójny: int cc; g.DFSearchAll(null, null, out cc); if (cc != 1) { return(null); } int?sum = buildCycle(g, out cycle); return(sum); } // TSP_TreeBased