예제 #1
0
        public static long RunParallelForPrim(this Graph g)
        {
            var used   = new HashSet <int>();
            var unused = new HashSet <int>();

            used.Add(0);

            for (var i = 1; i < g.VerticesNumber; ++i)
            {
                unused.Add(i);
            }

            long result = 0;

            while (unused.Count != 0)
            {
                var curs = new long[g.VerticesNumber];
                var ends = new int[g.VerticesNumber];

                Parallel.ForEach(used, v =>
                {
                    foreach (var u in unused)
                    {
                        var cost = g.AdjacencyMatrix[v, u];
                        if (cost != 0 && (curs[v] == 0 || curs[v] > cost))
                        {
                            curs[v] = cost;
                            ends[v] = u;
                        }
                    }
                });

                var cur = new Graph.Edge(0, 0, long.MaxValue);

                foreach (var v in used)
                {
                    if (cur.weight > curs[v])
                    {
                        cur = new Graph.Edge(v, ends[v], curs[v]);
                    }
                }

                result += cur.weight;
                unused.Remove(cur.end);
                used.Add(cur.end);
            }

            return(result);
        }
예제 #2
0
        public static long RunSequentialPrim(this Graph g)
        {
            var used   = new HashSet <int>();
            var unused = new HashSet <int>();

            used.Add(0);

            for (var i = 1; i < g.VerticesNumber; ++i)
            {
                unused.Add(i);
            }

            long result = 0;

            while (unused.Count != 0)
            {
                var cur = new Graph.Edge(0, 0, long.MaxValue);

                foreach (var v in used)
                {
                    foreach (var u in unused)
                    {
                        var cost = g.AdjacencyMatrix[v, u];
                        if (cost != 0 && cur.weight > cost)
                        {
                            cur = new Graph.Edge(v, u, cost);
                        }
                    }
                }

                result += cur.weight;
                unused.Remove(cur.end);
                used.Add(cur.end);
            }

            return(result);
        }
예제 #3
0
        public static long RunParallelThreadsPrim(this Graph g)
        {
            var used   = new HashSet <int>();
            var unused = new HashSet <int>();

            used.Add(0);

            for (var i = 1; i < g.VerticesNumber; ++i)
            {
                unused.Add(i);
            }

            long result = 0;

            while (unused.Count != 0)
            {
                var curs = new long[g.VerticesNumber];
                var ends = new int[g.VerticesNumber];

                var isDone    = new AutoResetEvent(false);
                var completed = used.Count;

                foreach (var v in used)
                {
                    ThreadPool.QueueUserWorkItem(_ =>
                    {
                        foreach (var u in unused)
                        {
                            var cost = g.AdjacencyMatrix[v, u];
                            if (cost != 0 && (curs[v] == 0 || curs[v] > cost))
                            {
                                curs[v] = cost;
                                ends[v] = u;
                            }
                        }

                        if (Interlocked.Decrement(ref completed) == 0)
                        {
                            isDone.Set();
                        }
                    });
                }

                isDone.WaitOne();

                var cur = new Graph.Edge(0, 0, long.MaxValue);

                foreach (var v in used)
                {
                    if (cur.weight > curs[v])
                    {
                        cur = new Graph.Edge(v, ends[v], curs[v]);
                    }
                }

                result += cur.weight;
                unused.Remove(cur.end);
                used.Add(cur.end);
            }

            return(result);
        }
예제 #4
0
        public static long RunParallelThreadsKruskal(this Graph g)
        {
            var dsu   = new DisjointSetUnion(g.VerticesNumber);
            var edges = new List <Graph.Edge>();

            var chunkSize = g.EdgesNumber;

            if (g.EdgesNumber > Environment.ProcessorCount)
            {
                chunkSize = g.EdgesNumber / Environment.ProcessorCount;
            }

            var chunksNumber = g.EdgesNumber / chunkSize;

            var chunks = new List <Graph.Edge> [chunksNumber];
            var tasks  = new List <Task>();
            var start  = new int[chunksNumber];

            for (int i = 0, chunk = chunkSize; i < g.EdgesNumber; i += chunk)
            {
                if (i + 2 * chunk > g.EdgesNumber)
                {
                    chunk = g.EdgesNumber - i;
                }

                chunks[i / chunkSize] = new List <Graph.Edge>();

                for (var j = i; j < i + chunk; ++j)
                {
                    chunks[i / chunkSize].Add(g.Edges[j]);
                }

                var i1 = i / chunkSize;
                tasks.Add(Task.Run(() => chunks[i1].Sort()));
            }

            Task.WaitAll(tasks.ToArray());

            while (edges.Count != g.EdgesNumber)
            {
                var cur = new Graph.Edge();
                var id  = -1;

                for (var i = 0; i < chunks.Length; ++i)
                {
                    if (start[i] < chunks[i].Count && (id == -1 || chunks[i][start[i]].weight < cur.weight))
                    {
                        id  = i;
                        cur = chunks[i][start[i]];
                    }
                }

                edges.Add(cur);
                ++start[id];
            }

            long result = 0;

            foreach (var edge in edges)
            {
                if (dsu.Find(edge.start) != dsu.Find(edge.end))
                {
                    result += edge.weight;
                    dsu.Union(edge.start, edge.end);
                }
            }

            return(result);
        }