Exemple #1
0
        /// <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);
        }
Exemple #2
0
        /// <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