Beispiel #1
0
    public static void Main()
    {
        int[]     NM = IntLine();
        int       N = NM[0], M = NM[1];
        UnionFind uf = new UnionFind(N);

        for (int i = 0; i < M; i++)
        {
            int[] a = IntLine();
            uf.Unite(a[0] - 1, a[1] - 1);
        }
        Dictionary <int, int> nd = new Dictionary <int, int>();

        for (int i = 0; i < N; i++)
        {
            var a = uf.Root(i);
            if (!nd.ContainsKey(a))
            {
                nd[a] = 1;
            }
            else
            {
                nd[a]++;
            }
        }
        int ans = 0;

        foreach (var k in nd.Keys)
        {
            ans += (nd[k] - uf.data[k] == 1 ? 1 : 0);
        }
        Console.WriteLine(ans);
    }
Beispiel #2
0
    static void Main()
    {
        int[]     nkl   = Console.ReadLine().Split().Select(int.Parse).ToArray();
        UnionFind road  = new UnionFind(nkl[0]);
        UnionFind train = new UnionFind(nkl[0]);

        for (int i = 0; i < nkl[1]; i++)
        {
            int[] a = Console.ReadLine().Split().Select(int.Parse).ToArray();
            road.Union(a[0] - 1, a[1] - 1);
        }
        for (int i = 0; i < nkl[2]; i++)
        {
            int[] a = Console.ReadLine().Split().Select(int.Parse).ToArray();
            train.Union(a[0] - 1, a[1] - 1);
        }
        Dictionary <long, int> dict = new Dictionary <long, int>();

        for (int i = 0; i < nkl[0]; i++)
        {
            long key = (long)road.Parent(i) * int.MaxValue + (long)train.Parent(i);
            if (!dict.ContainsKey(key))
            {
                dict.Add(key, 0);
            }
            dict[key]++;
        }
        int[] ans = new int[nkl[0]];
        for (int i = 0; i < nkl[0]; i++)
        {
            long key = (long)road.Parent(i) * int.MaxValue + (long)train.Parent(i);
            ans[i] = dict[key];
        }
        Console.WriteLine(string.Join(" ", ans));
    }
Beispiel #3
0
    static void Main()
    {
        int n = int.Parse(Console.ReadLine());

        Tuple <int[], int>[] vert = Enumerable.Range(0, n).Select(x => new Tuple <int[], int>(Console.ReadLine().Split().Select(int.Parse).ToArray(), x)).ToArray();

        Tuple <int[], int>[] sortbyx = vert.OrderBy(x => x.Item1[0]).ToArray();
        Tuple <int[], int>[] sortbyy = vert.OrderBy(x => x.Item1[1]).ToArray();

        List <Edge> edges = new List <Edge>();

        edges.AddRange(temp(sortbyx));
        edges.AddRange(temp(sortbyy));

        Edge[]    edge = edges.OrderBy(x => x.Length).ToArray();
        UnionFind uf   = new UnionFind(n);
        int       cost = 0;

        for (int i = 0; i < edge.Length; i++)
        {
            if (!uf.IsSameGroup(edge[i].Start, edge[i].End))
            {
                uf.Union(edge[i].Start, edge[i].End);
                cost += edge[i].Length;
            }
        }
        Console.WriteLine(cost);
    }
Beispiel #4
0
    static void putAns(int[] a, int[] b, int n, int m)
    {
        var ans = new long[m + 1];
        var uf  = new UnionFind(n + 10);

        ans[0] = (long)n * (n - 1) / 2L;
        for (int i = 0; i < m; i++)
        {
            if (uf.IsSameGroup(a[i], b[i]))
            {
                ans[i + 1] = ans[i];
            }
            else
            {
                long wa = uf.getMem(a[i]);
                long wb = uf.getMem(b[i]);
                ans[i + 1] = ans[i] - wa * wb;
                uf.Unite(a[i], b[i]);
            }
        }
        Array.Reverse(ans);
        var sb = new StringBuilder();

        for (int i = 1; i <= m; i++)
        {
            sb.Append(string.Format("{0}\n", ans[i]));
        }
        Console.Write(sb);
    }
Beispiel #5
0
    public static void Main()
    {
        var         n     = NextInt;
        var         m     = NextInt;
        List <Edge> edges = new List <Edge>();

        for (int i = 0; i < n; i++)
        {
            edges.Add(new Edge()
            {
                From = 0, To = i + 1, Cost = NextLong
            });
        }
        for (int i = 0; i < m; i++)
        {
            edges.Add(new Edge()
            {
                From = NextInt, To = NextInt, Cost = NextLong
            });
        }
        long      res = 0;
        UnionFind uf  = new UnionFind(n + 1);

        foreach (var edge in edges.OrderBy(x => x.Cost))
        {
            if (uf.TryUnite(edge.From, edge.To))
            {
                res += edge.Cost;
            }
        }
        Console.WriteLine(res);
    }
        private void TwoSitesCheck(UnionFind unionFind)
        {
            unionFind.Union(2, 8);

            Assert.IsTrue(unionFind.IsConnected(2, 8));
            Assert.IsFalse(unionFind.IsConnected(1, 5));
        }
Beispiel #7
0
    static void Solve(IO io)
    {
        var n = io.I;
        var m = io.I;

        var uf = new UnionFind(n);

        for (var i = 0; i < m; i++)
        {
            var a = io.I - 1;
            var b = io.I - 1;

            uf.Union(a, b);
        }

        var ans = 0;

        for (var i = 1; i < n; i++)
        {
            if (uf.Union(i - 1, i))
            {
                ans++;
            }
        }

        io.Write(ans);
    }
Beispiel #8
0
    public int MinCostToSupplyWater(int n, int[] wells, int[][] pipes)
    {
        List <int[]> orderedEdges = new List <int[]>(n + 1 + pipes.Length);

        for (int i = 0; i < wells.Length; i++)
        {
            orderedEdges.Add(new int[] { 0, i + 1, wells[i] });
        }

        for (int i = 0; i < pipes.Length; i++)
        {
            int[] edge = pipes[i];
            orderedEdges.Add(edge);
        }

        orderedEdges.Sort((a, b) => a[2] - b[2]);

        UnionFind uf        = new UnionFind(n);
        int       totalCost = 0;

        foreach (int[] edge in orderedEdges)
        {
            int houseOne = edge[0];
            int houseTwo = edge[1];
            int cost     = edge[2];
            if (uf.Union(houseOne, houseTwo))
            {
                totalCost += cost;
            }
        }

        return(totalCost);
    }
Beispiel #9
0
        /// <summary>
        /// Connects any orphaned sections of the map together.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public static T ConnectOrphanedSections <T>(T map) where T : class, IMap, new()
        {
            var floodFillAnalyzer         = new FloodFillAnalyzer(map);
            var returnMap                 = map.Clone <T>();
            List <MapSection> mapSections = floodFillAnalyzer.GetMapSections();
            var unionFind                 = new UnionFind(mapSections.Count);

            while (unionFind.Count > 1)
            {
                for (int i = 0; i < mapSections.Count; i++)
                {
                    int                 closestMapSectionIndex = FindNearestMapSection(mapSections, i, unionFind);
                    MapSection          closestMapSection      = mapSections[closestMapSectionIndex];
                    IEnumerable <ICell> tunnelCells            = map.GetCellsAlongLine(mapSections[i].Bounds.Center.X, mapSections[i].Bounds.Center.Y,
                                                                                       closestMapSection.Bounds.Center.X, closestMapSection.Bounds.Center.Y);
                    ICell previousCell = null;
                    foreach (ICell cell in tunnelCells)
                    {
                        returnMap.SetCellProperties(cell.X, cell.Y, true, true);
                        if (previousCell != null)
                        {
                            if (cell.X != previousCell.X || cell.Y != previousCell.Y)
                            {
                                returnMap.SetCellProperties(cell.X + 1, cell.Y, true, true);
                            }
                        }
                        previousCell = cell;
                    }
                    unionFind.Union(i, closestMapSectionIndex);
                }
            }
            return(returnMap);
        }
Beispiel #10
0
            public void Solve()
            {
                // ARC097 D
                int N = NextInt(), M = NextInt();
                var P = NextIntList();

                var uf = new UnionFind(N);

                M.REP(i =>
                {
                    int xi = NextInt() - 1, yi = NextInt() - 1;
                    uf.Unite(xi, yi);
                });

                var cnt = 0;

                for (int i = 0; i < N; i++)
                {
                    if (uf.IsSameGroup(P[i] - 1, i))
                    {
                        cnt++;
                    }
                }

                cnt.WL();

                return;
            }
        public KruskalMST(WeightedUnDirectedGraph g)
        {
            this.G           = g;
            this.MSTEdges    = new Queue <WeightedUndirectedEdge>();
            this.TotalWeight = 0;

            minHeap = new MinHeap <WeightedUndirectedEdge>(this.G.GetVertices() * this.G.GetVertices());
            Uf      = new UnionFind(G.GetVertices());

            foreach (var vertex in G.GetVerticesList())
            {
                foreach (var edge in G.GetAdjacentEdges(vertex))
                {
                    minHeap.Insert(edge);
                }
            }

            while (!minHeap.IsEmpty())
            {
                WeightedUndirectedEdge edge = minHeap.ExtractMin();
                int u = edge.Either();
                int v = edge.Other(u);

                if (!Uf.Connected(u, v))
                {
                    MSTEdges.Enqueue(edge);
                    TotalWeight += edge.Weight();
                    Uf.Union(u, v);
                }
            }
        }
        public int MinCostConnectPoints(int[][] points)
        {
            this.points = points;
            int pointCount = points.Length;
            var edges      = new List <Edge>();

            for (int i = 0; i < pointCount - 1; i++)
            {
                for (int j = i + 1; j < pointCount; j++)
                {
                    edges.Add(new Edge(i, j, GetCost(i, j)));
                }
            }
            edges.Sort();
            var uf  = new UnionFind(pointCount);
            int ans = 0;

            foreach (var edge in edges)
            {
                if (!uf.Insert(edge.I, edge.J))
                {
                    continue;
                }
                ans += edge.Length;
            }
            return(ans);
        }
        void InitPQ()
        {
            uf = VertexNode.MakeUnionFind(heMesh);

            for (int i = 0; i < uf.NumNodes; i++)
            {
                uf[i].Quadric = vertQuadrics[i];
            }

            PQ = new FastPriorityQueue <FaceNode>(heMesh.Faces.Length);

            nodes = new FaceNode[heMesh.Faces.Length];

            for (int i = 0; i < heMesh.Faces.Length; i++)
            {
                Face f = heMesh.Faces[i];
                if (f.IsBoundary)
                {
                    continue;
                }
                nodes[i] = new FaceNode(f);

                Edge  lowestCost = OptimalEdge(f);
                float cost       = Cost(lowestCost);

                PQ.Enqueue(nodes[i], cost);
            }
        }
Beispiel #14
0
    static void Main()
    {
        var n = int.Parse(Console.ReadLine());
        var a = Console.ReadLine().Split().Select(int.Parse).ToList();

        a.Add(a.Aggregate(0, (x, y) => x ^ y));
        var b = Console.ReadLine().Split().Select(int.Parse).ToList();

        b.Add(b.Aggregate(0, (x, y) => x ^ y));
        if (a.OrderBy(x => x).Zip(b.OrderBy(x => x), (x, y) => x != y).Any(x => x))
        {
            Console.WriteLine(-1);
            return;
        }

        var       compressed = a.Distinct().OrderBy(x => x).Select((elem, count) => new { elem, count }).ToDictionary(x => x.elem, x => x.count);
        int       sameCount  = 0;
        UnionFind uf         = new UnionFind(compressed.Count);

        for (int i = 0; i < n; i++)
        {
            if (a[i] == b[i])
            {
                sameCount++;
            }
            uf.TryUnite(compressed[a[i]], compressed[b[i]]);
        }
        //全ての違う変数を動かす+閉路の数だけ動かす必要がある 始点を閉路に組み込めているならば-1
        Console.WriteLine((n - sameCount) + uf.AllRepresents.Count(x => 2 <= uf.GetSize(x)) - (n != sameCount && b.IndexOf(a.Last()) != n ? 1 : 0));
    }
Beispiel #15
0
        public int[] HitBricks(int[][] grid, int[][] hits)
        {
            int[] result = new int[hits.Length];
            for (int i = 0; i < hits.Length; i++)
            {
                grid[hits[i][0]][hits[i][1]] -= 1;
            }
            int       size = grid.Length * grid[0].Length;
            UnionFind uf   = new UnionFind(size + 1);

            for (int i = 0; i < grid[0].Length; i++)
            {
                if (grid[0][i] == 1)
                {
                    uf.Union(i, size);
                }
            }
            for (int i = 1; i < grid.Length; i++)
            {
                for (int j = 0; j < grid[0].Length; j++)
                {
                    if (grid[i][j] == 1)
                    {
                        if (grid[i - 1][j] == 1)
                        {
                            uf.Union((i - 1) * grid[0].Length + j, i * grid[0].Length + j);
                        }
                        if (j > 0 && grid[i][j - 1] == 1)
                        {
                            uf.Union(i * grid[0].Length + j - 1, i * grid[0].Length + j);
                        }
                    }
                }
            }
            for (int i = hits.Length - 1; i > 0; i--)
            {
                grid[hits[i][0]][hits[i][1]] += 1;

                if (grid[hits[i][0]][hits[i][1]] == 1)
                {
                    int preCount = uf.GetSize(size);
                    if (hits[i][0] == 0)
                    {
                        uf.Union(hits[i][1], size);
                    }
                    for (int j = 0; j < 4; j++)
                    {
                        var x = hits[i][0] + step[j][0];
                        var y = hits[i][1] + step[j][0];
                        if (x >= 0 && y >= 0 && x < grid.Length && y < grid[0].Length && grid[x][y] == 1)
                        {
                            uf.Union(hits[i][0] * grid[0].Length + hits[i][1], x * grid[0].Length + y);
                        }
                    }
                    int unionedCount = uf.GetSize(size);
                    result[i] = Math.Max(0, unionedCount - preCount - 1);
                }
            }
            return(result);
        }
Beispiel #16
0
    public static void Main()
    {
        int[] NM = IntLine();
        int   N = NM[0], M = NM[1];

        int[]     ps   = IntLine();
        UnionFind tree = new UnionFind(N);

        for (int i = 0; i < M; i++)
        {
            int[] box = IntLine().Select(v => v - 1).ToArray();;
            tree.Unite(box[0], box[1]);
        }

        int ans = 0;

        for (int i = 0; i < N; i++)
        {
            if (tree.Same(i, ps[i] - 1))
            {
                ans++;
            }
        }
        Console.WriteLine(ans);
    }
Beispiel #17
0
        public int NumIslands(char[][] grid)
        {
            if (grid == null || grid.Length == 0)
            {
                return(0);
            }
            rows   = grid.Length;
            colums = grid[0].Length;

            UnionFind uf = new UnionFind(grid);

            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < colums; j++)
                {
                    if (grid[i][j] == '0')
                    {
                        continue;
                    }
                    for (int k = 0; k < 4; k++)
                    {
                        int newx = i + d[k, 0];
                        int newy = j + d[k, 1];
                        if (newx >= 0 && newy >= 0 && newx < rows && newy < colums && grid[newx][newy] == '1')
                        {
                            uf.Union(i * colums + j, newx * colums + newy);
                        }
                    }
                }
            }
            return(uf.Count);
        }
Beispiel #18
0
    static void Main(string[] args)
    {
        var nm   = Input.ar;
        var edge = new List <Edge>();

        for (var i = 0; i < nm[0]; i++)
        {
            var cost = Input.num;
            edge.Add(new Edge(i, nm[0], cost));
        }
        for (var i = 0; i < nm[1]; i++)
        {
            var e = Input.ar;
            edge.Add(new Edge(e[0] - 1, e[1] - 1, e[2]));
        }
        edge = edge.OrderBy(v => v.Item3).ToList();
        var uf = UnionFind <int> .Make(nm[0] + 1);

        var res = 0L;

        foreach (var eg in edge)
        {
            if (!uf.IsSame(eg.Item1, eg.Item2))
            {
                uf.Union(eg.Item1, eg.Item2);
                res += eg.Item3;
            }
        }
        WriteLine(res);
    }
Beispiel #19
0
    public static void Main()
    {
        long      N  = NextLong();
        int       M  = NextInt();
        UnionFind UF = new UnionFind((int)N);

        Pair[] p = new Pair[M];
        for (int i = 0; i < M; i++)
        {
            p[i].x = NextInt() - 1;
            p[i].y = NextInt() - 1;
        }
        Array.Reverse(p);
        List <long> ans = new List <long>();
        long        box = (N - 1) * N / 2;

        for (int i = 0; i < M; i++)
        {
            ans.Add(box);
            if (UF.Same(p[i].x, p[i].y))
            {
                continue;
            }
            else
            {
                box -= UF.Get(p[i].x) * UF.Get(p[i].y);
            }
            UF.Unite(p[i].x, p[i].y);
        }
        ans.Reverse();
        ans.ToList().ForEach(Console.WriteLine);
    }
        public void Should_Connect_Two_By_Two()
        {
            //given
            UnionFind<String> uf = new UnionFind<String>();
            String[] cc = new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" };

            //when
            uf.AddRange(cc);
            for(int i = 0; i < cc.Length; i += 2)
            {
                uf.Merge(i, i + 1);
            }

            //Then
            uf.AddRange(cc);
            for (int i = 0; i < cc.Length; i += 2)
            {
                bool connected = uf.IsConnected(i, i + 1);
                Assert.IsTrue(connected);
                if(i+2 < cc.Length)
                {
                    connected = uf.IsConnected(i + 1, i + 2);
                    Assert.IsFalse(connected);
                }
            }

        }
        private void ConnectCaves()
        {
            var mapAnalyzer = new MapAnalyzer(_map);
            List <MapSection> mapSections = mapAnalyzer.GetMapSections();
            var unionFind = new UnionFind(mapSections.Count);

            while (unionFind.Count > 1)
            {
                for (int i = 0; i < mapSections.Count; i++)
                {
                    int                closestMapSectionIndex = FindNearestMapSection(mapSections, i, unionFind);
                    MapSection         closestMapSection      = mapSections[closestMapSectionIndex];
                    IEnumerable <Cell> tunnelCells            = _map.GetCellsAlongLine(mapSections[i].Bounds.Center.X, mapSections[i].Bounds.Center.Y,
                                                                                       closestMapSection.Bounds.Center.X, closestMapSection.Bounds.Center.Y);
                    Cell previousCell = null;
                    foreach (Cell cell in tunnelCells)
                    {
                        _map.SetCellProperties(cell.X, cell.Y, true, true);
                        if (previousCell != null)
                        {
                            if (cell.X != previousCell.X || cell.Y != previousCell.Y)
                            {
                                _map.SetCellProperties(cell.X + 1, cell.Y, true, true);
                            }
                        }
                        previousCell = cell;
                    }
                    unionFind.Union(i, closestMapSectionIndex);
                }
            }
        }
Beispiel #22
0
                /// <summary>
                /// Returns the lightest tree that connects all the vertices in the graph.
                /// </summary>
                /// <returns>A list of edges that make up the minimum spanning tree.</returns>
                public List <Edge> Kruskal()
                {
                    List <Edge>      mst       = new List <Edge>();
                    List <Edge>      edges     = new List <Edge>();
                    UnionFind <uint> unionFind = new UnionFind <uint>();

                    foreach (Vertex v in this.Vertices.Values)
                    {
                        foreach (Edge e in v.Neighbours.Values)
                        {
                            edges.Add(e);
                        }
                    }

                    edges.Sort((x, y) => { return(x.Weight.CompareTo(y.Weight)); });
                    foreach (Vertex v in this.Vertices.Values)
                    {
                        unionFind.Make(v.ID);
                    }

                    foreach (Edge e in edges)
                    {
                        if (unionFind.Find(e.From) != unionFind.Find(e.To))
                        {
                            mst.Add(e);
                            unionFind.Union(e.From, e.To);
                        }
                    }

                    return(mst);
                }
Beispiel #23
0
    public static void Main()
    {
        int n  = int.Parse(Console.ReadLine());
        var ab = Enumerable.Repeat(0, n).Select(_ => Console.ReadLine().Split().Select(int.Parse).ToArray()).ToArray();

        UnionFind uf = new UnionFind(400000 + 1);

        foreach (var item in ab)
        {
            uf.TryUnite(item[0], item[1]);
        }

        int[] edgeCount = new int[uf.Size];
        for (int i = 0; i < n; i++)
        {
            edgeCount[uf.Find(ab[i][0])]++;
        }
        long res = 0;

        for (int i = 0; i < edgeCount.Length; i++)
        {
            res += Min(edgeCount[i], uf.GetSize(i));
        }
        Console.WriteLine(res);
    }
Beispiel #24
0
    static void Main()
    {
        int N  = cin.Int();
        int M  = cin.Int();
        var uf = new UnionFind(N + 10);

        var A = new int[M];
        var B = new int[M];

        for (int i = 0; i < M; i++)
        {
            A[i] = cin.Int();
            B[i] = cin.Int();
            if (!uf.IsSameGroup(A[i], B[i]))
            {
                uf.Unite(A[i], B[i]);
            }
        }

        var hash = new HashSet <int>();

        for (int i = 1; i <= N; i++)
        {
            hash.Add(uf.Root(i));
        }
        Console.WriteLine(hash.Count - 1);
        Console.ReadLine();
    }
Beispiel #25
0
        /// <summary>
        /// Builds the minimum-spanning tree using Kruskal's algorithm in O(|E|*log|E|)
        /// where |E| is the number of Edges
        /// and |V| the number of vertices (nodes) in the Graph
        /// </summary>
        /// <returns></returns>
        private Tree BuildMinimumSpanningTreeKruskal()
        {
            int N         = m_nodes.Count;
            var unionFind = new UnionFind(m_nodes); //O(|V|)

            Func <Edge, Edge, int> cmp = (a, b) => a.CompareTo(b);
            var heap = new List <Edge>(EdgeCount);

            foreach (var e in Edges)
            {
                heap.HeapEnqueue(cmp, e);
            }

            var tree = new Tree(this);

            long i = 0;

            //O(|E|*log|E|)
            while (tree.EdgeCount < N - 1)
            {
                var edge = heap.HeapDequeue(cmp);
                i++;

                //O(1) amortized
                if (unionFind.Add(edge.Index0, edge.Index1))
                {
                    //O(1)
                    tree.AddEdge(edge);
                }
            }

            //O(|V| + |E|*log|E|)
            return(tree);
        }
Beispiel #26
0
        public void Solve()
        {
            int n = cin.nextint;
            int m = cin.nextint;

            int[,] edge = new int[m, 2];

            for (int i = 0; i < m; i++)
            {
                edge[i, 0] = cin.nextint - 1;
                edge[i, 1] = cin.nextint - 1;
            }

            UnionFind uf = new UnionFind(n);

            long[] ans = new long[m];
            ans[m - 1] = (long)n * (n - 1) / 2;

            for (int i = m - 1; i > 0; i--)
            {
                if (uf.IsSame(edge[i, 0], edge[i, 1]))
                {
                    ans[i - 1] = ans[i];
                }
                else
                {
                    long size = uf.size[uf.Root(edge[i, 0])] * uf.size[uf.Root(edge[i, 1])];
                    ans[i - 1] = ans[i] - size;

                    uf.Unite(edge[i, 0], edge[i, 1]);
                }
            }
            Console.WriteLine(String.Join("\n", ans));
        }
                /// <summary>
                /// Returns the lightest tree that connects all the node in the graph.
                /// </summary>
                /// <param name="graph">The graph to calculate the minimum spanning tree of.</param>
                /// <returns>A list of edges that make up the minimum spanning tree.</returns>
                public static List <IWeightedGraphEdge> MinimumSpanningTree(IGraph <IWeightedGraphEdge> graph)
                {
                    List <IWeightedGraphEdge> mst       = new List <IWeightedGraphEdge>();
                    List <IWeightedGraphEdge> edges     = new List <IWeightedGraphEdge>();
                    UnionFind <uint>          unionFind = new UnionFind <uint>();

                    foreach (Dictionary <uint, IWeightedGraphEdge> dict in graph.Edges.Values)
                    {
                        foreach (IWeightedGraphEdge e in dict.Values)
                        {
                            edges.Add(e);
                        }
                    }

                    edges.Sort((x, y) => { return(x.Weight.CompareTo(y.Weight)); });
                    foreach (IGraphNode <IWeightedGraphEdge> n in graph.Nodes.Values)
                    {
                        unionFind.Make(n.ID);
                    }

                    foreach (IWeightedGraphEdge e in edges)
                    {
                        if (unionFind.Find(e.From) != unionFind.Find(e.To))
                        {
                            mst.Add(e);
                            unionFind.Union(e.From, e.To);
                        }
                    }

                    return(mst);
                }
Beispiel #28
0
        static void Method(string[] args)
        {
            int[]     nm        = ReadInts();
            int       n         = nm[0];
            int       m         = nm[1];
            UnionFind unionFind = new UnionFind(n);

            for (int i = 0; i < m; i++)
            {
                int[] xyz = ReadInts();
                unionFind.Unite(xyz[0] - 1, xyz[1] - 1);
            }

            int cnt = 0;

            for (int i = 0; i < n; i++)
            {
                if (i == unionFind.Root(i))
                {
                    cnt++;
                }
            }

            WriteLine(cnt);
        }
Beispiel #29
0
        /// <summary>
        /// Sprawdza czy dla podanych par ulic możliwy jest przejazd między nimi (z użyciem być może innych ulic).
        /// </summary>
        /// <returns>Lista, w której na i-tym miejscu jest informacja czy przejazd między ulicami w i-tej parze z wejścia jest możliwy</returns>
        // etap 2
        public bool[] CheckStreetsPairs(Street[] streets, int[] streetsToCheck1, int[] streetsToCheck2)
        {
            int n = streetsToCheck1.Length;
            int S = streets.Length;

            if (S == 0 || n == 0)
            {
                throw new ArgumentException();
            }
            bool[]    ret = new bool[n];
            UnionFind u   = new UnionFind(S);

            for (int i = 0; i < S - 1; ++i)
            {
                for (int j = i + 1; j < S; ++j)
                {
                    if (CheckIntersection(streets[i], streets[j]) != 0)
                    {
                        u.Union(i, j);
                    }
                }
            }
            for (int i = 0; i < n; ++i)
            {
                if (u.Find(streetsToCheck1[i]) == u.Find(streetsToCheck2[i]))
                {
                    ret[i] = true;
                }
            }
            return(ret);
        }
Beispiel #30
0
    static void Main()
    {
        int n, q;

        sc.Multi(out n, out q);
        var uf = new UnionFind(n * 2);

        for (int i = 0; i < q; i++)
        {
            int w, x, y, z;
            sc.Multi(out w, out x, out y, out z);
            --x;
            --y;
            if (w == 1)
            {
                if (z % 2 == 0)
                {
                    uf.unite(x, y);
                    uf.unite(x + n, y + n);
                }
                else
                {
                    uf.unite(x, y + n);
                    uf.unite(x + n, y);
                }
            }
            else
            {
                Prt(uf.same(x, y) ? "YES" : "NO");
            }
        }
        sw.Flush();
    }
Beispiel #31
0
    static void putAns(int[] a, int[] b, int n, int m)
    {
        var ans = new long[m + 1];
        var uf  = new UnionFind(n + 10);

        ans[0] = (long)n * (n - 1) / 2L;
        for (int i = 0; i < m; i++)
        {
            if (uf.IsSameGroup(a[i], b[i]))
            {
                ans[i + 1] = ans[i];
            }
            else
            {
                long wa = uf.getMem(a[i]);
                long wb = uf.getMem(b[i]);
                ans[i + 1] = ans[i] - wa * wb;
                uf.Unite(a[i], b[i]);
            }
        }
        Array.Reverse(ans);
        for (int i = 1; i <= m; i++)
        {
            Console.WriteLine(ans[i]);
        }
    }
Beispiel #32
0
 public void ConnectedTest1()
 {
     var uf = new UnionFind<double>(EqualityComparer<double>.Default);
     uf.Union(3.14, 2.71);
     uf.Union(1, 2);
     uf.Union(3.14, 1.618);
     uf.Union(2.71, 0);
     Assert.Equal(false, uf.Connected(1, 3.14));
     Assert.Equal(true, uf.Connected(2.71, 1.618));
     Assert.Equal(true, uf.Connected(0, 1.618));
 }
        public void StringTest()
        {
            var uf = new UnionFind();

            Assert.IsFalse(uf.IsSameGroup("1", "2"));
            Assert.IsFalse(uf.IsSameGroup("2", "3"));
            Assert.IsFalse(uf.IsSameGroup("1", "3"));

            uf.Unite("1", "3");
            Assert.IsFalse(uf.IsSameGroup("1", "2"));
            Assert.IsFalse(uf.IsSameGroup("2", "3"));
            Assert.IsTrue(uf.IsSameGroup("1", "3"));
        }
        public void TypeMixedTest()
        {
            var uf = new UnionFind();

            Assert.IsFalse(uf.IsSameGroup(1, "1"));
            Assert.IsFalse(uf.IsSameGroup("2", 2));
            Assert.IsFalse(uf.IsSameGroup("two", 2));

            uf.Unite(1, "1");
            uf.Unite(2, "2");
            uf.Unite(2, "two");

            Assert.IsTrue(uf.IsSameGroup(1, "1"));
            Assert.IsTrue(uf.IsSameGroup("2", 2));
            Assert.IsTrue(uf.IsSameGroup("two", 2));        //2 and "two" should be the same group!
            Assert.IsTrue(uf.IsSameGroup("2", "two"));
        }
        public void Ordinal()
        {
            var uf = new UnionFind();
            Assert.IsFalse(uf.IsSameGroup(1, 2));
            Assert.IsFalse(uf.IsSameGroup(2, 3));
            Assert.IsFalse(uf.IsSameGroup(1, 3));

            uf.Unite(1, 3);
            Assert.IsFalse(uf.IsSameGroup(1, 2));
            Assert.IsFalse(uf.IsSameGroup(2, 3));
            Assert.IsTrue(uf.IsSameGroup(1, 3));

            uf.Unite(2, 3);
            Assert.IsTrue(uf.IsSameGroup(1, 2));
            Assert.IsTrue(uf.IsSameGroup(2, 3));
            Assert.IsTrue(uf.IsSameGroup(1, 3));

            uf.Unite(50, 51);
            uf.Unite(52, 53);
            Assert.IsTrue(uf.IsSameGroup(50, 51));
            Assert.IsTrue(uf.IsSameGroup(52, 53));
            Assert.IsFalse(uf.IsSameGroup(50, 53));
            uf.Unite(53, 54);
            Assert.IsTrue(uf.IsSameGroup(52, 54));
            uf.Unite(50, 54);
            Assert.IsTrue(uf.IsSameGroup(50, 53));
            Assert.IsTrue(uf.IsSameGroup(50, 54));
            Assert.IsTrue(uf.IsSameGroup(50, 51));

            uf.Unite(70, 71);
            uf.Unite(70, 72);
            uf.Unite(73, 72);
            Assert.IsTrue(uf.IsSameGroup(70, 73));
            Assert.IsTrue(uf.IsSameGroup(73, 70));
            Assert.IsTrue(uf.IsSameGroup(73, 72));

            uf.Unite(99, 98);
            uf.Unite(0, 98);
            Assert.IsTrue(uf.IsSameGroup(98, 99));
            Assert.IsTrue(uf.IsSameGroup(99, 0));
            Assert.IsTrue(uf.IsSameGroup(98, 0));
        }
        public void Run()
        {
            MinHeap<Edge> minHeap = new MinHeap<Edge>();
            foreach(Edge e in graph.Edges())
            {
                minHeap.Push(e);
            }

            UnionFind<int> uf = new UnionFind<int>();
            while(minHeap.Count > 0 && mst.Count < graph.VerticesCount - 1)
            {
                Edge e = minHeap.Pop();
                int v = e.GetEither();
                int w = e.GetOther(v);
                if(!uf.IsConnected(v, w))
                {
                    uf.Merge(v, w);
                    mst.Enqueue(e);
                }
            }
        }
                /// <summary>
                /// Returns the lightest tree that connects all the vertices in the graph.
                /// </summary>
                /// <returns>A list of edges that make up the minimum spanning tree.</returns>
                public List<Edge> Kruskal()
                {
                    List<Edge> mst = new List<Edge>();
                    List<Edge> edges = new List<Edge>();
                    UnionFind<uint> unionFind = new UnionFind<uint>();
                    foreach (Vertex v in this.Vertices.Values)
                        foreach (Edge e in v.Neighbours.Values)
                            edges.Add(e);

                    edges.Sort((x, y) => { return x.Weight.CompareTo(y.Weight); });
                    foreach (Vertex v in this.Vertices.Values)
                        unionFind.Make(v.ID);

                    foreach (Edge e in edges)
                        if (unionFind.Find(e.From) != unionFind.Find(e.To))
                        {
                            mst.Add(e);
                            unionFind.Union(e.From, e.To);
                        }

                    return mst;
                }
                /// <summary>
                /// Returns the lightest tree that connects all the node in the graph.
                /// </summary>
                /// <param name="graph">The graph to calculate the minimum spanning tree of.</param>
                /// <returns>A list of edges that make up the minimum spanning tree.</returns>
                public static List<IWeightedGraphEdge> MinimumSpanningTree(IGraph<IWeightedGraphEdge> graph)
                {
                    List<IWeightedGraphEdge> mst = new List<IWeightedGraphEdge>();
                    List<IWeightedGraphEdge> edges = new List<IWeightedGraphEdge>();
                    UnionFind<uint> unionFind = new UnionFind<uint>();
                    foreach (Dictionary<uint, IWeightedGraphEdge> dict in graph.Edges.Values)
                        foreach (IWeightedGraphEdge e in dict.Values)
                            edges.Add(e);

                    edges.Sort((x, y) => { return x.Weight.CompareTo(y.Weight); });
                    foreach (IGraphNode<IWeightedGraphEdge> n in graph.Nodes.Values)
                        unionFind.Make(n.ID);

                    foreach (IWeightedGraphEdge e in edges)
                        if (unionFind.Find(e.From) != unionFind.Find(e.To))
                        {
                            mst.Add(e);
                            unionFind.Union(e.From, e.To);
                        }

                    return mst;
                }
        // find objects
        public static Dictionary<Tuple<int, int>, List<Tuple<int, int>>> Groups(int[,] image)
        {
            // union find to store sets of all pixels in object
            UnionFind<Tuple<int, int>> unionFind = new UnionFind<Tuple<int, int>>();
            for (int x = 0; x < image.GetLength(0); x++)
                for (int y = 0; y < image.GetLength(1); y++)
                {
                    if (image[x, y] == 0)
                        continue;

                    Tuple<int, int> xy = new Tuple<int, int>(x, y);
                    unionFind.Make(xy);
                    if (x > 0)
                        unionFind.Union(xy, new Tuple<int, int>(x - 1, y));
                    if (y > 0)
                        unionFind.Union(xy, new Tuple<int, int>(x, y - 1));
                }

            // turns union find "inside out": (pixel->set identifier)->(set identifier->all pixels in set)
            Dictionary<Tuple<int, int>, List<Tuple<int, int>>> labels = new Dictionary<Tuple<int, int>, List<Tuple<int, int>>>();
            for (int x = 0; x < image.GetLength(0); x++)
                for (int y = 0; y < image.GetLength(1); y++)
                {
                    if (image[x, y] == 0)
                        continue;

                    Tuple<int, int> xy = new Tuple<int, int>(x, y), label = unionFind.Find(xy);
                    List<Tuple<int, int>> list;
                    if (!labels.TryGetValue(label, out list))
                    {
                        list = new List<Tuple<int, int>>();
                        labels[label] = list;
                    }
                    list.Add(xy);
                }

            return labels;
        }
Beispiel #40
0
        private static void BuildNavCellConnectivityGrid(
            uint colomnCount,
            uint rowCount,
            BitArray navMeshData,
            out NavCell[] navCells,
            out uint nonEmptyNavCellCount)
        {
            UnionFind<uint> navCellUnion = new UnionFind<uint>();

            // Create an initial set of nav cells
            // Any valid cell gets a connectivity id of 0
            // Any invalid cell gets a connectivity id of EMPTY_NAV_CELL
            // Valid nav cells get added to the nav cell union set
            navCells = new NavCell[rowCount * colomnCount];
            nonEmptyNavCellCount = 0;

            for (int navCellIndex = 0; navCellIndex < navMeshData.Length; ++navCellIndex)
            {
                if (navMeshData[navCellIndex])
                {
                    uint pvsCellIndex = nonEmptyNavCellCount++;

                    navCells[navCellIndex] = new NavCell(0, pvsCellIndex);

                    navCellUnion.AddElement((uint)navCellIndex);
                }
                else
                {
                    navCells[navCellIndex] = new NavCell();
                }
            }

            // Union together all neighboring nav cells
            for (int unionElementIndex = 0; unionElementIndex < navCellUnion.SetSize; ++unionElementIndex)
            {
                uint navCellIndex = navCellUnion.GetElement(unionElementIndex);

                for (MathConstants.eDirection direction = MathConstants.eDirection.first;
                     direction < MathConstants.eDirection.count;
                     ++direction)
                {
                    uint neighborNavCellIndex;

                    if (TryGetValidNeighborNavCellIndex(
                            navCells,
                            colomnCount,
                            rowCount,
                            navCellIndex,
                            direction,
                            out neighborNavCellIndex))
                    {
                        navCellUnion.Union(navCellIndex, neighborNavCellIndex);
                    }
                }
            }

            // Write the final connectivity IDs back into the nav cells
            for (int unionElementIndex = 0; unionElementIndex < navCellUnion.SetSize; ++unionElementIndex)
            {
                uint navCellIndex = navCellUnion.GetElement(unionElementIndex);
                int connectivityID = navCellUnion.FindRootIndex(unionElementIndex);

                navCells[navCellIndex].connectivityId = (short)connectivityID;
            }
        }
Beispiel #41
0
        private bool ProcessImage(Color[,] image, CIELAB[,] imageLAB)
        {
            double thresh = 5;
            UnionFind<CIELAB> uf = new UnionFind<CIELAB>((a,b)=>(a.SqDist(b)<=thresh));
            int[,] assignments = uf.ConnectedComponents(imageLAB);//Util.Map<Color, CIELAB>(image, Util.RGBtoLAB));
            int numC = -1;
            for(int i=0; i<image.GetLength(0); i++)
                for (int j=0; j<image.GetLength(1); j++)
                    numC = Math.Max(numC, assignments[i,j]+1);
            if (numC >= 2)
                RemoveBackground(image, imageLAB);

            //if it is a black and white image (with num connected components >= 2), it's not a valid color image
            return !(isBlackWhite(image, imageLAB) && numC >= 2);
        }
Beispiel #42
0
        private void RemoveBackground(Color[,] image, CIELAB[,] imageLAB)
        {
            //check perimeter to see if it's mostly black or white

            //RGB to LAB
            CIELAB black = new CIELAB(0, 0, 0);
            CIELAB white = new CIELAB(100, 0, 0);

            int width = image.GetLength(0);
            int height = image.GetLength(1);

            CIELAB[,] labs = imageLAB;//Util.Map<Color, CIELAB>(image, (c) => Util.RGBtoLAB(c));

            int numBlack = 0;
            int numWhite = 0;
            int thresh = 3 * 3;
            List<Point> perimeterIdx = new List<Point>();
            double totalPerimeter = 4 * width + 4 * height;
            double bgThresh = totalPerimeter*0.75;

            for (int i = 0; i < width; i++)
            {
                //top
                for (int j = 0; j < 2; j++)
                {
                    if (black.SqDist(labs[i, j])<thresh)
                        numBlack++;
                    if (white.SqDist(labs[i, j]) < thresh)
                        numWhite++;
                    perimeterIdx.Add(new Point(i, j));
                }

                //bottom
                for (int j = height - 2; j < height; j++)
                {
                    perimeterIdx.Add(new Point(i, j));
                    if (black.SqDist(labs[i, j]) < thresh)
                        numBlack++;
                    if (white.SqDist(labs[i, j]) < thresh)
                        numWhite++;
                }
            }

            for (int j = 0; j < height; j++)
            {
                //left
                for (int i=0; i<2; i++)
                {
                    perimeterIdx.Add(new Point(i,j));
                    if (black.SqDist(labs[i, j]) < thresh)
                        numBlack++;
                    if (white.SqDist(labs[i, j]) < thresh)
                        numWhite++;
                }

                //right
                for (int i=width-2; i<width; i++)
                {
                    perimeterIdx.Add(new Point(i, j));
                    if (black.SqDist(labs[i, j]) < thresh)
                        numBlack++;
                    if (white.SqDist(labs[i, j]) < thresh)
                        numWhite++;
                }
            }

            if (numBlack >= bgThresh || numWhite >= bgThresh)
            {
                //connected components
                UnionFind<CIELAB> uf = new UnionFind<CIELAB>((a,b) => a.SqDist(b)<thresh);
                int[,] cc = uf.ConnectedComponents(labs);

                SortedSet<int> ids = new SortedSet<int>();

                //go around the perimeter to collect the right ids
                foreach (Point p in perimeterIdx)
                {
                    if (numWhite > numBlack)
                    {
                        if (labs[p.X, p.Y].SqDist(white) < thresh)
                            ids.Add(cc[p.X, p.Y]);
                    }
                    else
                    {
                        if (labs[p.X, p.Y].SqDist(black) < thresh)
                            ids.Add(cc[p.X, p.Y]);
                    }
                }

                //fill the bitmap with transparency
                for (int i = 0; i < width; i++)
                {
                    for (int j = 0; j < height; j++)
                    {
                        if (ids.Contains(cc[i, j]))
                            image[i, j] = Color.FromArgb(0, 0, 0, 0);
                    }
                }
            }
        }
        private bool VerifyRoomAccessibility(
            DungeonLayout layout,
            Dictionary<int, Portal> portalIdToPortalMap)
        {
            UnionFind<RoomKey> roomUnion = new UnionFind<RoomKey>();
            RoomKey targetRoomKey = new RoomKey();
            bool success = true;

            // Do a first pass over the rooms to fill out the union and the portal map
            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                iterator.Valid;
                iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room room = layout.GetRoomByIndex(roomIndex);

                // Add the room to the union set
                roomUnion.AddElement(room.room_key);
            }

            // Union together all of the rooms connected by portals
            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                iterator.Valid;
                iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room room = layout.GetRoomByIndex(roomIndex);

                foreach (Portal portal in room.portals)
                {
                    Portal targetPortal= portalIdToPortalMap[portal.target_portal_id];

                    targetRoomKey.game_id= layout.GameID;
                    targetRoomKey.x= targetPortal.room_x;
                    targetRoomKey.y= targetPortal.room_y;
                    targetRoomKey.z= targetPortal.room_z;

                    roomUnion.Union(room.room_key, targetRoomKey);
                }
            }

            // Verify that all rooms share the same connectivity id
            int sharedConnectivityId = -1;
            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                iterator.Valid;
                iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room room = layout.GetRoomByIndex(roomIndex);

                int roomConnectivityId= roomUnion.FindRootIndex(room.room_key);

                if (sharedConnectivityId != -1)
                {
                    if (sharedConnectivityId != roomConnectivityId)
                    {
                        _logger.WriteLine("DungeonValidator: FAILED: Found room not connected to other rooms in dungeon!");
                        _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                        _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                            room.room_key.x, room.room_key.y, room.room_key.z));
                        success= false;
                        break;
                    }
                }
                else
                {
                    sharedConnectivityId= roomConnectivityId;
                }
            }

            return success;
        }
        //Test the quantization, connected components on different color layers, and output the descriptor
        private void OutputPatterns_Click(object sender, RoutedEventArgs e)
        {
            //Create output directories
            Directory.CreateDirectory(outdir + "\\cc\\");
            Directory.CreateDirectory(outdir + "\\quantized\\");
            Directory.CreateDirectory(outdir + "\\mesh\\");

            //read in the patterns and save out their layers
            String[] files = System.IO.Directory.GetFiles(System.IO.Path.Combine(imagedir));
            List<PatternItem> patterns = PatternIO.GetPatterns(imagedir);

            foreach (PatternItem p in patterns)
            {
                Bitmap image= new Bitmap(p.FullPath);
                String basename = p.Name;

                //TODO: sometimes keys are not found in patterns.csv...will need to look into recovering missing info. For now, just ignore those patterns
                if (!palettes.ContainsKey(basename))
                    continue;

                PaletteData palette = palettes[basename];

                ColorTemplate template = new ColorTemplate(image, palette);

                //output the template descriptor
                SegmentMesh mesh = new SegmentMesh(template);
                PatternIO.SaveMesh(mesh, p, Path.Combine(outdir, "mesh"));

                if (outputDebugImages)
                {
                    Bitmap result = template.DebugQuantization();
                    PatternIO.SavePattern(result, p, Path.Combine(outdir, "quantized"), "_quantized");
                    PatternIO.SavePattern(result, p, Path.Combine(outdir, "quantized"), "_original");

                    //save the connected components
                    UnionFind<Color> uf = new UnionFind<Color>((a, b) => (a.GetHashCode() == b.GetHashCode()));
                    Color[,] resultArray = Util.BitmapToArray(result);
                    int[,] cc = uf.ConnectedComponentsNoiseRemoval(resultArray);

                    int numColors = palette.colors.Count();
                    for (int i = 0; i < numColors; i++)
                    {
                        Bitmap debug = uf.RenderComponents(cc, resultArray, palette.colors[i]);
                        PatternIO.SavePattern(debug, p, Path.Combine(outdir, "cc"), "_" + i);
                        debug.Dispose();
                    }
                    result.Dispose();
                }
                image.Dispose();

            }
        }
        /// <summary>
        /// Constructs the graph pattern specified by the MATCH clause. 
        /// The graph pattern may consist of multiple fully-connected sub-graphs.
        /// </summary>
        /// <param name="query">The SELECT query block</param>
        /// <returns>A graph object contains all the connected componeents</returns>
        private MatchGraph ConstructGraph(WSelectQueryBlock query)
        {
            if (query == null || query.MatchClause == null)
                return null;

            var unionFind = new UnionFind();
            var edgeColumnToAliasesDict = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
            var pathDictionary = new Dictionary<string, MatchPath>(StringComparer.OrdinalIgnoreCase);
            var matchClause = query.MatchClause;
            var nodes = new Dictionary<string, MatchNode>(StringComparer.OrdinalIgnoreCase);
            var connectedSubGraphs = new List<ConnectedComponent>();
            var subGrpahMap = new Dictionary<string, ConnectedComponent>(StringComparer.OrdinalIgnoreCase);
            var parent = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            unionFind.Parent = parent;

            // Constructs the graph pattern specified by the path expressions in the MATCH clause
            foreach (var path in matchClause.Paths)
            {
                var index = 0;
                MatchEdge preEdge = null;
                for (var count = path.PathEdgeList.Count; index < count; ++index)
                {
                    var currentNodeTableRef = path.PathEdgeList[index].Item1;
                    var currentEdgeColumnRef = path.PathEdgeList[index].Item2;
                    var currentNodeExposedName = currentNodeTableRef.BaseIdentifier.Value;
                    var nextNodeTableRef = index != count - 1
                        ? path.PathEdgeList[index + 1].Item1
                        : path.Tail;
                    var nextNodeExposedName = nextNodeTableRef.BaseIdentifier.Value;
                    var patternNode = nodes.GetOrCreate(currentNodeExposedName);
                    if (patternNode.NodeAlias == null)
                    {
                        patternNode.NodeAlias = currentNodeExposedName;
                        patternNode.Neighbors = new List<MatchEdge>();
                        patternNode.External = false;
                        var nodeTable = _context[currentNodeExposedName] as WNamedTableReference;
                        if (nodeTable != null)
                        {
                            patternNode.NodeTableObjectName = nodeTable.TableObjectName;
                            if (patternNode.NodeTableObjectName.SchemaIdentifier == null)
                                patternNode.NodeTableObjectName.Identifiers.Insert(0, new Identifier {Value = "dbo"});
                        }
                    }

                    string edgeAlias = currentEdgeColumnRef.Alias;
                    if (edgeAlias == null)
                    {
                        var currentEdgeName = currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last().Value;
                        edgeAlias = string.Format("{0}_{1}_{2}", currentNodeExposedName, currentEdgeName,
                            nextNodeExposedName);
                        if (edgeColumnToAliasesDict.ContainsKey(currentEdgeName))
                        {
                            edgeColumnToAliasesDict[currentEdgeName].Add(edgeAlias);
                        }
                        else
                        {
                            edgeColumnToAliasesDict.Add(currentEdgeName, new List<string> { edgeAlias });
                        }
                    }

                    Identifier edgeIdentifier = currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last();
                    string schema = patternNode.NodeTableObjectName.SchemaIdentifier.Value.ToLower();
                    string nodeTableName = patternNode.NodeTableObjectName.BaseIdentifier.Value;
                    string bindTableName =
                        _context.EdgeNodeBinding[
                            new Tuple<string, string>(nodeTableName.ToLower(), edgeIdentifier.Value.ToLower())].ToLower();
                    MatchEdge edge;
                    if (currentEdgeColumnRef.MinLength == 1 && currentEdgeColumnRef.MaxLength == 1)
                    {
                        edge = new MatchEdge
                        {
                            SourceNode = patternNode,
                            EdgeColumn = currentEdgeColumnRef,
                            EdgeAlias = edgeAlias,
                            BindNodeTableObjName =
                                new WSchemaObjectName(
                                    new Identifier {Value = schema},
                                    new Identifier {Value = bindTableName}
                                    ),
                        };
                        _context.AddEdgeReference(edge);
                    }
                    else
                    {
                        MatchPath matchPath = new MatchPath
                        {
                            SourceNode = patternNode,
                            EdgeColumn = currentEdgeColumnRef,
                            EdgeAlias = edgeAlias,
                            BindNodeTableObjName =
                                new WSchemaObjectName(
                                    new Identifier {Value = schema},
                                    new Identifier {Value = bindTableName}
                                    ),
                            MinLength = currentEdgeColumnRef.MinLength,
                            MaxLength = currentEdgeColumnRef.MaxLength,
                            ReferencePathInfo = false,
                            AttributeValueDict = currentEdgeColumnRef.AttributeValueDict
                        };
                        _context.AddEdgeReference(matchPath);
                        pathDictionary[edgeAlias] = matchPath;
                        edge = matchPath;
                    }

                    if (preEdge != null)
                    {
                        preEdge.SinkNode = patternNode;
                    }
                    preEdge = edge;

                    if (!parent.ContainsKey(currentNodeExposedName))
                        parent[currentNodeExposedName] = currentNodeExposedName;
                    if (!parent.ContainsKey(nextNodeExposedName))
                        parent[nextNodeExposedName] = nextNodeExposedName;

                    unionFind.Union(currentNodeExposedName, nextNodeExposedName);


                    patternNode.Neighbors.Add(edge);


                }
                var tailExposedName = path.Tail.BaseIdentifier.Value;
                var tailNode = nodes.GetOrCreate(tailExposedName);
                if (tailNode.NodeAlias == null)
                {
                    tailNode.NodeAlias = tailExposedName;
                    tailNode.Neighbors = new List<MatchEdge>();
                    var nodeTable = _context[tailExposedName] as WNamedTableReference;
                    if (nodeTable != null)
                    {
                        tailNode.NodeTableObjectName = nodeTable.TableObjectName;
                        if (tailNode.NodeTableObjectName.SchemaIdentifier == null)
                            tailNode.NodeTableObjectName.Identifiers.Insert(0, new Identifier {Value = "dbo"});
                    }
                }
                if (preEdge != null)
                    preEdge.SinkNode = tailNode;
            }

            // Puts nodes into subgraphs
            foreach (var node in nodes)
            {
                string root = unionFind.Find(node.Key);
                if (!subGrpahMap.ContainsKey(root))
                {
                    var subGraph = new ConnectedComponent();
                    subGraph.Nodes[node.Key] = node.Value;
                    foreach (var edge in node.Value.Neighbors)
                    {
                        subGraph.Edges[edge.EdgeAlias] = edge;
                    }
                    subGrpahMap[root] = subGraph;
                    connectedSubGraphs.Add(subGraph);
                    subGraph.IsTailNode[node.Value] = false;
                }
                else
                {
                    var subGraph = subGrpahMap[root];
                    subGraph.Nodes[node.Key] = node.Value;
                    foreach (var edge in node.Value.Neighbors)
                    {
                        subGraph.Edges[edge.EdgeAlias] = edge;
                    }
                    subGraph.IsTailNode[node.Value] = false;
                }
            }

            var graph = new MatchGraph
            {
                ConnectedSubGraphs = connectedSubGraphs,
            };
            unionFind.Parent = null;

            // When an edge in the MATCH clause is not associated with an alias, 
            // assigns to it a default alias: sourceAlias_EdgeColumnName_sinkAlias. 
            // Also rewrites edge attributes anywhere in the query that can be bound to this default alias. 
            var replaceTableRefVisitor = new ReplaceEdgeReferenceVisitor();
            replaceTableRefVisitor.Invoke(query, edgeColumnToAliasesDict);

            // Rematerializes node tables in the MATCH clause which are defined in the upper-level context
            // and join them with the upper-level table references.
            RematerilizeExtrenalNodeTableReference(query, nodes);

            // Transforms the path reference in the SELECT elements into a 
            // scalar function to display path information.
            TransformPathInfoDisplaySelectElement(query, pathDictionary);

            
            return graph;
        }
        /// <summary>
        /// Construct Graph from the match clause. The Graph can consist of multiple connected SubGraph.
        /// Not supported in this version
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        private MatchGraph ConstructGraph(WSelectQueryBlock query)
        {
            var unionFind = new UnionFind();
            if (query.MatchClause == null)
                return null;
            var edgeTableReferenceDict = new Dictionary<string, List<string>>(StringComparer.CurrentCultureIgnoreCase);
            var matchClause = query.MatchClause;
            var nodes = new Dictionary<string, MatchNode>(StringComparer.CurrentCultureIgnoreCase);
            var connectedSubGraphs = new List<ConnectedComponent>();
            var subGrpahMap = new Dictionary<string, ConnectedComponent>(StringComparer.CurrentCultureIgnoreCase);
            var parent = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
            unionFind.Parent = parent;
            HashSet<Tuple<string, string>> nodeTypes = new HashSet<Tuple<string, string>>();

            //Construct Graph from Match Pattern
            foreach (var path in matchClause.Paths)
            {
                var index = 0;
                MatchEdge preEdge = null;
                for (var count = path.PathNodeList.Count; index < count; ++index)
                {
                    var currentNode = path.PathNodeList[index].Item1;
                    var currentEdge = path.PathNodeList[index].Item2;
                    var currentNodeExposedName = currentNode.BaseIdentifier.Value;
                    var nextNode = index != count - 1
                        ? path.PathNodeList[index + 1].Item1
                        : path.Tail;
                    var nextNodeExposedName = nextNode.BaseIdentifier.Value;
                    var node = nodes.GetOrCreate(currentNodeExposedName);
                    if (node.NodeAlias == null)
                    {
                        node.NodeAlias = currentNodeExposedName;
                        node.Neighbors = new List<MatchEdge>();
                        node.External = false;
                        var nodeTable = _context[currentNodeExposedName] as WNamedTableReference;
                        if (nodeTable != null)
                        {
                            node.TableObjectName = nodeTable.TableObjectName;
                            if (node.TableObjectName.SchemaIdentifier == null)
                                node.TableObjectName.Identifiers.Insert(0, new Identifier { Value = "dbo" });
                            var nodeTypeTuple = WNamedTableReference.SchemaNameToTuple(node.TableObjectName);
                            if (!nodeTypes.Contains(nodeTypeTuple))
                                nodeTypes.Add(nodeTypeTuple);

                        }
                    }

                    if (currentEdge.AliasRole == AliasType.Default)
                    {
                        var currentEdgeName = currentEdge.MultiPartIdentifier.Identifiers.Last().Value;
                        if (edgeTableReferenceDict.ContainsKey(currentEdgeName))
                        {
                            edgeTableReferenceDict[currentEdgeName].Add(currentEdge.Alias);
                        }
                        else
                        {
                            edgeTableReferenceDict.Add(currentEdgeName, new List<string> { currentEdge.Alias });
                        }
                    }
                    var edge = new MatchEdge
                    {
                        SourceNode = node,
                        EdgeColumn = new WColumnReferenceExpression
                        {
                            MultiPartIdentifier = new WMultiPartIdentifier
                            {
                                Identifiers = new List<Identifier>
                                {
                                    new Identifier {Value = node.NodeAlias},
                                    currentEdge.MultiPartIdentifier.Identifiers.Last()
                                }
                            }
                        },
                        EdgeAlias = currentEdge.Alias
                    };

                    if (preEdge != null)
                    {
                        preEdge.SinkNode = node;
                    }
                    preEdge = edge;

                    if (!parent.ContainsKey(currentNodeExposedName))
                        parent[currentNodeExposedName] = currentNodeExposedName;
                    if (!parent.ContainsKey(nextNodeExposedName))
                        parent[nextNodeExposedName] = nextNodeExposedName;

                    unionFind.Union(currentNodeExposedName, nextNodeExposedName);


                    node.Neighbors.Add(edge);


                    _context.AddEdgeReference(currentEdge.Alias, edge.SourceNode.TableObjectName, currentEdge);
                }
                var tailExposedName = path.Tail.BaseIdentifier.Value;
                var tailNode = nodes.GetOrCreate(tailExposedName);
                if (tailNode.NodeAlias == null)
                {
                    tailNode.NodeAlias = tailExposedName;
                    tailNode.Neighbors = new List<MatchEdge>();
                    var nodeTable = _context[tailExposedName] as WNamedTableReference;
                    if (nodeTable != null)
                    {
                        tailNode.TableObjectName = nodeTable.TableObjectName;
                        if (tailNode.TableObjectName.SchemaIdentifier == null)
                            tailNode.TableObjectName.Identifiers.Insert(0, new Identifier { Value = "dbo" });
                        var nodeTypeTuple = WNamedTableReference.SchemaNameToTuple(tailNode.TableObjectName);
                        if (!nodeTypes.Contains(nodeTypeTuple))
                            nodeTypes.Add(nodeTypeTuple);
                    }
                }
                if (preEdge != null) 
                    preEdge.SinkNode = tailNode;
            }

            // Put nodes into subgraphs
            foreach (var node in nodes)
            {
                string root = unionFind.Find(node.Key);
                if (!subGrpahMap.ContainsKey(root))
                {
                    var subGraph = new ConnectedComponent();
                    subGraph.Nodes[node.Key] = node.Value;
                    foreach (var edge in node.Value.Neighbors)
                    {
                        subGraph.Edges[edge.EdgeAlias] = edge;
                    }
                    subGrpahMap[root] = subGraph;
                    connectedSubGraphs.Add(subGraph);
                    subGraph.IsTailNode[node.Value] = false;
                }
                else
                {
                    var subGraph = subGrpahMap[root];
                    subGraph.Nodes[node.Key] = node.Value;
                    foreach (var edge in node.Value.Neighbors)
                    {
                        subGraph.Edges[edge.EdgeAlias] = edge;
                    }
                    subGraph.IsTailNode[node.Value] = false;
                }
            }

            // Replace Edge name alias with proper alias in the query
            var replaceTableRefVisitor = new ReplaceTableRefVisitor();
            replaceTableRefVisitor.Invoke(query, edgeTableReferenceDict);
            

            // If a table alias in the MATCH clause is defined in an upper-level context, 
            // to be able to translate this MATCH clause, this table alias must be re-materialized 
            // in the FROM clause of the current context and joined with the corresponding table
            // in the upper-level context. 
            var tableRefs = query.FromClause.TableReferences;
            var tableSet = new HashSet<string>(StringComparer.CurrentCultureIgnoreCase);
            var newTableRefs = new List<WTableReference>();
            for (int index = 0; index < tableRefs.Count; ++index)
            {
                var table = tableRefs[index] as WNamedTableReference;
                if (table == null)
                {
                    newTableRefs.Add(tableRefs[index]);
                    continue;
                }
                var tableTuple = WNamedTableReference.SchemaNameToTuple(table.TableObjectName);
                if (!nodeTypes.Contains(tableTuple))
                {
                    newTableRefs.Add(table);
                }
                else
                {
                    tableSet.Add(table.ExposedName.Value);
                }
            }
            query.FromClause = new WFromClause
            {
                TableReferences = newTableRefs,
            };
            WBooleanExpression whereCondiction = null;
            foreach (var node in nodes)
            {
                if (!tableSet.Contains(node.Key))
                {
                    node.Value.External = true;
                    var newWhereCondition = new WBooleanComparisonExpression
                    {
                        ComparisonType = BooleanComparisonType.Equals,
                        FirstExpr = new WColumnReferenceExpression
                        {
                            MultiPartIdentifier = new WMultiPartIdentifier(
                                new Identifier { Value = node.Key },
                                new Identifier { Value = "GlobalNodeId" })
                        },
                        SecondExpr = new WColumnReferenceExpression
                        {
                            MultiPartIdentifier = new WMultiPartIdentifier(
                                new Identifier { Value = node.Value.RefAlias },
                                new Identifier { Value = "GlobalNodeId" })
                        },
                    };
                    whereCondiction = WBooleanBinaryExpression.Conjunction(whereCondiction, newWhereCondition);
                }
            }
            if (whereCondiction != null)
            {
                if (query.WhereClause == null)
                {
                    query.WhereClause = new WWhereClause { SearchCondition = whereCondiction };
                }
                else
                {
                    if (query.WhereClause.SearchCondition == null)
                    {
                        query.WhereClause.SearchCondition = whereCondiction;
                    }
                    else
                    {
                        query.WhereClause.SearchCondition = new WBooleanBinaryExpression
                        {
                            BooleanExpressionType = BooleanBinaryExpressionType.And,
                            FirstExpr = new WBooleanParenthesisExpression
                            {
                                Expression = query.WhereClause.SearchCondition
                            },
                            SecondExpr = new WBooleanParenthesisExpression
                            {
                                Expression = whereCondiction
                            }
                        };
                    }
                }
            }

            var graph = new MatchGraph
            {
                ConnectedSubGraphs = connectedSubGraphs,
                NodeTypesSet = nodeTypes,
            };
            unionFind.Parent = null;
            return graph;
        }
        public SegmentMesh(ColorTemplate template)
        {
            int numGroups = template.NumSlots();
            imageWidth = template.Width();
            imageHeight = template.Height();

            groups = new List<SegmentGroup>();
            segments = new List<Segment>();

            //now populate the segments and segment groups
            //filter out groups that have no members (due to quantization)
            Dictionary<int, int> slotToGroup = new Dictionary<int, int>();
            for (int i = 0; i < numGroups; i++)
            {
                if (template.PixelsInSlot(i) > 0)
                {
                    slotToGroup.Add(i, groups.Count());
                    groups.Add(new SegmentGroup(template.OriginalSlotColor(i)));
                }
            }

            UnionFind<Color> uf = new UnionFind<Color>((a, b) => (a.GetHashCode() == b.GetHashCode()));
            Bitmap image = template.DebugQuantization();
            assignments = uf.ConnectedComponentsNoiseRemoval(Util.BitmapToArray(image));

            Dictionary<int, Segment> idToSegment = new Dictionary<int, Segment>();
            int totalAdjacencyPerimeter = 0;
            Dictionary<int, HashSet<Point>> idToPerimeter = new Dictionary<int, HashSet<Point>>();

            //populate segments
            int width = image.Width;
            int height = image.Height;
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    int id = assignments[i, j];
                    if (!idToSegment.ContainsKey(id))
                    {
                        idToSegment.Add(id, new Segment(id));
                        idToPerimeter.Add(id, new HashSet<Point>());
                    }

                    idToSegment[id].points.Add(new Point(i, j));
                    idToSegment[id].groupId = slotToGroup[template.GetSlotId(i, j)];

                    //look for 8-neighbor adjacencies, 2 pixels away
                    //TODO: measure adjacency strength and filter?
                    for (int dx = -2; dx <= 2; dx++)
                    {
                        for (int dy = -2; dy <= 2; dy++)
                        {
                            int x = i + dx;
                            int y = j + dy;
                            if (x >= 0 && x < width && y >= 0 && y < height)
                            {
                                int nid = assignments[x, y];
                                if (nid != id)
                                {
                                    idToSegment[id].adjacencies.Add(nid);

                                    //keep track of the total perimeter, and individual segment perimeters
                                    //don't double count the same point for each segment
                                    if (!idToPerimeter[id].Contains(new Point(x, y)))
                                    {
                                        idToPerimeter[id].Add(new Point(x, y));
                                        totalAdjacencyPerimeter++;

                                        //keep track of the adjacecy strength per segment
                                        if (!idToSegment[id].adjacencyStrength.ContainsKey(nid))
                                            idToSegment[id].adjacencyStrength.Add(nid, 0);
                                        idToSegment[id].adjacencyStrength[nid]++;
                                    }
                                    else
                                    {
                                        Console.WriteLine("Point already counted");
                                    }
                                }
                            }
                            else
                            {
                                //might as well be consistent here, and take into account the borders of the image when determining
                                //enclosure. We don't need to do this for the totalAdjacencyPerimeter, because that is just a normalization
                                //for the adjacency strengths of segments within the image
                                if (!idToPerimeter[id].Contains(new Point(x,y)))
                                {
                                    idToPerimeter[id].Add(new Point(x,y));
                                }
                            }
                        }
                    }
                }
            }

            //finalize segment list and adjacency list
            Dictionary<int, int> idToIdx = new Dictionary<int, int>();
            foreach (int id in idToSegment.Keys)
            {
                segments.Add(idToSegment[id]);
                idToIdx.Add(id, segments.Count() - 1);
            }

            //finalize adjacencies
            for (int i = 0; i < segments.Count(); i++)
            {
                SortedSet<int> renamedAdj = new SortedSet<int>();
                foreach (int a in segments[i].adjacencies)
                    renamedAdj.Add(idToIdx[a]);
                segments[i].adjacencies = renamedAdj;

                //finalize adjacency strengths
                int sid = assignments[segments[i].points.First().X, segments[i].points.First().Y];

                Dictionary<int, double> renamedAdjStrength = new Dictionary<int, double>();
                foreach (int nid in segments[i].adjacencyStrength.Keys)
                {
                    double pixelsAdj = segments[i].adjacencyStrength[nid];
                    renamedAdjStrength.Add(idToIdx[nid], pixelsAdj / totalAdjacencyPerimeter);
                    segments[i].enclosureStrength.Add(idToIdx[nid], new Tuple<double, double>(pixelsAdj / idToPerimeter[sid].Count(), pixelsAdj / idToPerimeter[nid].Count()));
                }
                segments[i].adjacencyStrength = renamedAdjStrength;

            }

            //finalize groups
            for (int i = 0; i < segments.Count(); i++)
            {
                int groupId = segments[i].groupId;
                groups[groupId].members.Add(i);
            }

            //finalize segment list

            ClassifySegments();

            foreach (Segment s in segments)
            {
                ComputeFeatures(s);
            }

            foreach (SegmentGroup g in groups)
            {
                ComputeFeatures(g);
            }
        }
        /// <summary>
        /// Play the given workload in a polling manner and store the results in the given file
        /// </summary>
        /// <param name="workload">The workload</param>
        /// <param name="employees">The amount of employees generated for the workload</param>
        /// <param name="path">The path for the results</param>
        /// <returns>The measurement results</returns>
        private static Results PlayWorkloadClassic(List<WorkloadAction> workload, int employees, string path)
        {
            var sb = new StringBuilder();
            watch.Restart();

            var employeesList = new List<Employee>(employees);

            sb.AppendLine("Initializing graph");

            Console.WriteLine("Running workload on classic interface");

            for (int i = 0; i < employees; i++)
            {
                workload[i].Perform(employeesList, sb);
            }
            watch.Stop();
            var initTime = watch.ElapsedMilliseconds;

            var first = employeesList[0];
            var second = employeesList[1];

            sb.AppendFormat("Will query whether {0} and {1} are connected", first.Name, second.Name);
            sb.AppendLine();

            ScenarioGenerator.Evaluation = () =>
            {
                var analysis = new UnionFind<Employee>(e => e.Knows, employeesList);
                return analysis.AreConnected(first, second).ToString();
            };

            watch.Restart();
            for (int i = employees; i < workload.Count; i++)
            {
                workload[i].Perform(employeesList, sb);
            }

            watch.Stop();
            var main = watch.ElapsedMilliseconds;

            File.WriteAllText(path, sb.ToString());

            Console.WriteLine("Completed. Polling took {0}ms", watch.ElapsedMilliseconds);

            //var memory = MemoryMeter.ComputeMemoryConsumption(pollQuery);

            return new Results() { Initialization = initTime, MainWorkload = main };
        }
Beispiel #49
0
        private void inputImageBox_MouseDown(object sender, MouseEventArgs e)
        {
            if (this.data == null) return;

            int xx = e.X - (inputImageBox.Width - inputImageBox.Image.Width) / 2;
            int yy = e.Y - (inputImageBox.Height - inputImageBox.Image.Height) / 2;

            switch (currentStep)
            {
                case 5: // Compactness
                    decimal r = (decimal)Operations.Compactness(this.prevData, xx, yy);
                    decimal rLow = Math.Floor(r * 100) / 100;
                    decimal rHigh = Math.Ceiling(r * 100) / 100;
                    minComp.Value = Math.Min(minComp.Value, rLow);
                    maxComp.Value = Math.Max(maxComp.Value, rHigh);
                    break;

                case 6: // Area
                    decimal a = (decimal)Operations.Area(Operations.Perimeter(this.prevData, xx, yy));
                    decimal aLow = Math.Floor(a * 100) / 100;
                    decimal aHigh = Math.Ceiling(a * 100) / 100;
                    minArea.Value = Math.Min(minArea.Value, aLow);
                    maxArea.Value = Math.Max(maxArea.Value, aHigh);
                    break;

                case 7: // Convexity
                    UnionFind<Tuple<int, int>> unionFind = new UnionFind<Tuple<int, int>>();
                    for (int x = 0; x < this.prevData.GetLength(0); x++)
                        for (int y = 0; y < this.prevData.GetLength(1); y++)
                        {
                            if (this.prevData[x, y] == 0)
                                continue;

                            Tuple<int, int> xy = new Tuple<int, int>(x, y);
                            unionFind.Make(xy);
                            if (x > 0)
                                unionFind.Union(xy, new Tuple<int, int>(x - 1, y));
                            if (y > 0)
                                unionFind.Union(xy, new Tuple<int, int>(x, y - 1));
                        }

                    Tuple<int, int> root;
                    try
                    {
                        root = unionFind.Find(new Tuple<int, int>(xx, yy));
                    }
                    catch
                    {
                        return;
                    }
                    List<Tuple<int, int>> points = new List<Tuple<int, int>>();

                    for (int x = 0; x < this.prevData.GetLength(0); x++)
                    {
                        for (int y = 0; y < this.prevData.GetLength(1); y++)
                        {
                            if (this.prevData[x, y] == 0)
                                continue;

                            Tuple<int, int> pos = new Tuple<int, int>(x, y);
                            if (unionFind.Find(pos) == root)
                                points.Add(pos);
                        }
                    }

                    double hullArea = Operations.PolygonArea(Operations.ConvexHull(points));
                    double area = Operations.Area(Operations.Perimeter(this.prevData, xx, yy));
                    decimal c = (decimal) (area / hullArea);
                    decimal cLow = Math.Floor(c * 100) / 100;
                    decimal cHigh = Math.Ceiling(c * 100) / 100;
                    minConv.Value = Math.Min(minConv.Value, cLow);
                    maxConv.Value = Math.Max(maxConv.Value, cHigh);
                    break;

                default:
                    break;
            }
        }
        /// <summary>
        /// Constructs the graph pattern specified by the MATCH clause. 
        /// The graph pattern may consist of multiple fully-connected sub-graphs.
        /// </summary>
        /// <param name="query">The SELECT query block</param>
        /// <returns>A graph object contains all the connected componeents</returns>
        private MatchGraph ConstructGraph(WSelectQueryBlock query)
        {
            if (query == null || query.MatchClause == null)
                return null;

            var columnsOfNodeTables = _graphMetaData.ColumnsOfNodeTables;
            var nodeViewMapping = _graphMetaData.NodeViewMapping;
            var unionFind = new UnionFind();
            var edgeColumnToAliasesDict = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
            var pathDictionary = new Dictionary<string, MatchPath>(StringComparer.OrdinalIgnoreCase);
            var reversedEdgeDict = new Dictionary<string, MatchEdge>();
            var matchClause = query.MatchClause;
            var nodes = new Dictionary<string, MatchNode>(StringComparer.OrdinalIgnoreCase);
            var connectedSubGraphs = new List<ConnectedComponent>();
            var subGrpahMap = new Dictionary<string, ConnectedComponent>(StringComparer.OrdinalIgnoreCase);
            var parent = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            unionFind.Parent = parent;

            // Constructs the graph pattern specified by the path expressions in the MATCH clause
            foreach (var path in matchClause.Paths)
            {
                var index = 0;
                MatchEdge preEdge = null;
                for (var count = path.PathEdgeList.Count; index < count; ++index)
                {
                    var currentNodeTableRef = path.PathEdgeList[index].Item1;
                    var currentEdgeColumnRef = path.PathEdgeList[index].Item2;
                    var currentNodeExposedName = currentNodeTableRef.BaseIdentifier.Value;
                    var nextNodeTableRef = index != count - 1
                        ? path.PathEdgeList[index + 1].Item1
                        : path.Tail;
                    var nextNodeExposedName = nextNodeTableRef.BaseIdentifier.Value;
                    var patternNode = nodes.GetOrCreate(currentNodeExposedName);
                    if (patternNode.NodeAlias == null)
                    {
                        patternNode.NodeAlias = currentNodeExposedName;
                        patternNode.Neighbors = new List<MatchEdge>();
                        patternNode.External = false;
                        var nodeTable = _context[currentNodeExposedName] as WNamedTableReference;
                        if (nodeTable != null)
                        {
                            patternNode.NodeTableObjectName = nodeTable.TableObjectName;
                            if (patternNode.NodeTableObjectName.SchemaIdentifier == null)
                                patternNode.NodeTableObjectName.Identifiers.Insert(0, new Identifier {Value = "dbo"});
                        }
                    }

                    Identifier edgeIdentifier = currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last();
                    string schema = patternNode.NodeTableObjectName.SchemaIdentifier.Value.ToLower();
                    string nodeTableName = patternNode.NodeTableObjectName.BaseIdentifier.Value;
                    string bindTableName =
                        _context.EdgeNodeBinding[
                            new Tuple<string, string>(nodeTableName.ToLower(), edgeIdentifier.Value.ToLower())].ToLower();
                    var bindNodeTableObjName = new WSchemaObjectName(
                        new Identifier {Value = schema},
                        new Identifier {Value = bindTableName}
                        );
                    var edgeColumn =
                        columnsOfNodeTables[
                            WNamedTableReference.SchemaNameToTuple(bindNodeTableObjName)][
                                currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last().Value];
                    string edgeAlias = currentEdgeColumnRef.Alias;
                    //string revEdgeAlias = edgeAlias;
                    bool isReversed = path.IsReversed || edgeColumn.EdgeInfo.IsReversedEdge;
                    string currentRevEdgeName = null;

                    // get original edge name
                    var currentEdgeName = currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last().Value;
                    var originalSourceName = isReversed ?
                        (_context[nextNodeExposedName] as WNamedTableReference).TableObjectName.BaseIdentifier.Value
                        : (_context[currentNodeExposedName] as WNamedTableReference).TableObjectName.BaseIdentifier.Value;

                    if (isReversed)
                    {
                        var i = currentEdgeName.IndexOf(originalSourceName, StringComparison.OrdinalIgnoreCase) +
                            originalSourceName.Length;
                        currentRevEdgeName = currentEdgeName.Substring(i + 1,
                            currentEdgeName.Length - "Reversed".Length - i - 1);
                    }
                    else
                    {
                        var srcTuple = WNamedTableReference.SchemaNameToTuple(patternNode.NodeTableObjectName);
                        // [nodeView]-[edge]->[node/nodeView]
                        if (edgeColumn.Role == WNodeTableColumnRole.Edge && nodeViewMapping.ContainsKey(srcTuple))
                        {
                            var physicalNodeName =
                                _context.EdgeNodeBinding[new Tuple<string, string>(srcTuple.Item2, currentEdgeName.ToLower())];
                            currentRevEdgeName = physicalNodeName + "_" + currentEdgeName + "Reversed";
                        }
                        else
                        {
                            currentRevEdgeName = originalSourceName + "_" + currentEdgeName + "Reversed";
                        }
                    }

                    if (edgeAlias == null)
                    {
                        edgeAlias = !isReversed
                            ? string.Format("{0}_{1}_{2}", currentNodeExposedName, currentEdgeName, nextNodeExposedName)
                            : string.Format("{0}_{1}_{2}", nextNodeExposedName, currentRevEdgeName, currentNodeExposedName);

                        //when the current edge is a reversed edge, the key should still be the original edge name
                        //e.g.: TestDeleteEdgeWithTableAlias
                        var edgeNameKey = isReversed ? currentRevEdgeName : currentEdgeName;
                        if (edgeColumnToAliasesDict.ContainsKey(edgeNameKey))
                        {
                            edgeColumnToAliasesDict[edgeNameKey].Add(edgeAlias);
                        }
                        else
                        {
                            edgeColumnToAliasesDict.Add(edgeNameKey, new List<string> { edgeAlias });
                        }
                    }

                    MatchEdge edge, revEdge;
                    if (currentEdgeColumnRef.MinLength == 1 && currentEdgeColumnRef.MaxLength == 1)
                    {
                        var isEdgeView = edgeColumn.Role == WNodeTableColumnRole.EdgeView;
                        var hasRevEdge = edgeColumn.EdgeInfo.HasReversedEdge;
                        edge = new MatchEdge
                        {
                            IsEdgeView = isEdgeView,
                            IsReversedEdge = false,
                            HasReversedEdge = hasRevEdge,
                            SourceNode = patternNode,
                            EdgeColumn = currentEdgeColumnRef,
                            EdgeAlias = edgeAlias,
                            BindNodeTableObjName = bindNodeTableObjName,
                        };
                        _context.AddEdgeReference(edge);

                        if (hasRevEdge)
                        {
                            revEdge = new MatchEdge
                            {
                                IsEdgeView = isEdgeView,
                                IsReversedEdge = true,
                                SinkNode = patternNode,
                                EdgeColumn = new WEdgeColumnReferenceExpression()
                                {
                                    ColumnType = currentEdgeColumnRef.ColumnType,
                                    Alias = currentEdgeColumnRef.Alias,
                                    MaxLength = currentEdgeColumnRef.MaxLength,
                                    MinLength = currentEdgeColumnRef.MinLength,
                                    AttributeValueDict = currentEdgeColumnRef.AttributeValueDict,
                                    MultiPartIdentifier = new WMultiPartIdentifier(new Identifier()
                                    {
                                        QuoteType = currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last().QuoteType,
                                        Value = currentRevEdgeName,
                                    }),
                                },
                                EdgeAlias = edgeAlias,
                                //EdgeAlias = revEdgeAlias,
                            };
                            reversedEdgeDict[edge.EdgeAlias] = revEdge;
                        }
                    }
                    else
                    {
                        MatchPath matchPath = new MatchPath
                        {
                            SourceNode = patternNode,
                            EdgeColumn = currentEdgeColumnRef,
                            EdgeAlias = edgeAlias,
                            BindNodeTableObjName =
                                new WSchemaObjectName(
                                    new Identifier {Value = schema},
                                    new Identifier {Value = bindTableName}
                                    ),
                            MinLength = currentEdgeColumnRef.MinLength,
                            MaxLength = currentEdgeColumnRef.MaxLength,
                            ReferencePathInfo = false,
                            AttributeValueDict = currentEdgeColumnRef.AttributeValueDict
                        };
                        _context.AddEdgeReference(matchPath);
                        pathDictionary[edgeAlias] = matchPath;
                        edge = matchPath;
                    }

                    if (preEdge != null)
                    {
                        preEdge.SinkNode = patternNode;
                        if (preEdge.HasReversedEdge)
                        {
                            //var preSourceNode = preEdge.SourceNode;
                            var preEdgeBindNodeTableObjName = preEdge.BindNodeTableObjName;
                            var preEdgeColName = preEdge.EdgeColumn.MultiPartIdentifier.Identifiers.Last().Value;
                            var preEdgeColumn =
                                columnsOfNodeTables[
                                    WNamedTableReference.SchemaNameToTuple(preEdgeBindNodeTableObjName)][
                                        preEdgeColName];
                            var isEdgeView = preEdgeColumn.Role == WNodeTableColumnRole.EdgeView;
                            var isNodeView =
                                _graphMetaData.NodeViewMapping.ContainsKey(
                                    WNamedTableReference.SchemaNameToTuple(patternNode.NodeTableObjectName));

                            reversedEdgeDict[preEdge.EdgeAlias].SourceNode = patternNode;
                            // [node/nodeView]-[edgeView]->[node/nodeView]
                            if (isEdgeView)
                            {
                                reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = preEdgeBindNodeTableObjName;
                            }
                            // [node/nodeView]-[edge]->[nodeView]
                            else if (!isEdgeView && isNodeView)
                            {
                                reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = new WSchemaObjectName(
                                    new Identifier { Value = "dbo" },
                                    new Identifier { Value = preEdgeColumn.EdgeInfo.SinkNodes.First() }
                                    );
                            }
                            else
                            {
                                reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = new WSchemaObjectName(
                                    new Identifier { Value = schema },
                                    new Identifier { Value = bindTableName }
                                    );
                            }
                        }
                    }
                    preEdge = edge;

                    if (!parent.ContainsKey(currentNodeExposedName))
                        parent[currentNodeExposedName] = currentNodeExposedName;
                    if (!parent.ContainsKey(nextNodeExposedName))
                        parent[nextNodeExposedName] = nextNodeExposedName;

                    unionFind.Union(currentNodeExposedName, nextNodeExposedName);

                    patternNode.Neighbors.Add(edge);

                }
                var tailExposedName = path.Tail.BaseIdentifier.Value;
                var tailNode = nodes.GetOrCreate(tailExposedName);
                if (tailNode.NodeAlias == null)
                {
                    tailNode.NodeAlias = tailExposedName;
                    tailNode.Neighbors = new List<MatchEdge>();
                    var nodeTable = _context[tailExposedName] as WNamedTableReference;
                    if (nodeTable != null)
                    {
                        tailNode.NodeTableObjectName = nodeTable.TableObjectName;
                        if (tailNode.NodeTableObjectName.SchemaIdentifier == null)
                            tailNode.NodeTableObjectName.Identifiers.Insert(0, new Identifier {Value = "dbo"});
                    }
                }
                if (preEdge != null)
                {
                    preEdge.SinkNode = tailNode;
                    if (preEdge.HasReversedEdge)
                    {
                        var schema = tailNode.NodeTableObjectName.SchemaIdentifier.Value.ToLower();
                        var nodeTableName = tailNode.NodeTableObjectName.BaseIdentifier.Value;
                        //var preSourceNode = preEdge.SourceNode;
                        var preEdgeBindNodeTableObjName = preEdge.BindNodeTableObjName;
                        var preEdgeColName = preEdge.EdgeColumn.MultiPartIdentifier.Identifiers.Last().Value;
                        var preEdgeColumn =
                            columnsOfNodeTables[
                                WNamedTableReference.SchemaNameToTuple(preEdgeBindNodeTableObjName)][
                                    preEdgeColName];
                        var isEdgeView = preEdgeColumn.Role == WNodeTableColumnRole.EdgeView;
                        var isNodeView =
                            _graphMetaData.NodeViewMapping.ContainsKey(
                                WNamedTableReference.SchemaNameToTuple(tailNode.NodeTableObjectName));
                        reversedEdgeDict[preEdge.EdgeAlias].SourceNode = tailNode;
                        // [node/nodeView]-[edgeView]->[node/nodeView]
                        if (isEdgeView)
                        {
                            reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = preEdgeBindNodeTableObjName;
                        }
                        // [node/nodeView]-[edge]->[nodeView]
                        else if (!isEdgeView && isNodeView)
                        {
                            reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = new WSchemaObjectName(
                                new Identifier { Value = "dbo" },
                                new Identifier { Value = preEdgeColumn.EdgeInfo.SinkNodes.First() }
                                );
                        }
                        else
                        {
                            reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = new WSchemaObjectName(
                                new Identifier { Value = schema },
                                new Identifier { Value = nodeTableName.ToLower() }
                                );
                        }
                    }
                }
            }

            // Puts nodes into subgraphs
            foreach (var node in nodes)
            {
                string root = unionFind.Find(node.Key);
                if (!subGrpahMap.ContainsKey(root))
                {
                    var subGraph = new ConnectedComponent();
                    subGraph.Nodes[node.Key] = node.Value;
                    foreach (var edge in node.Value.Neighbors)
                    {
                        subGraph.Edges[edge.EdgeAlias] = edge;
                    }
                    subGrpahMap[root] = subGraph;
                    connectedSubGraphs.Add(subGraph);
                    subGraph.IsTailNode[node.Value] = false;
                }
                else
                {
                    var subGraph = subGrpahMap[root];
                    subGraph.Nodes[node.Key] = node.Value;
                    foreach (var edge in node.Value.Neighbors)
                    {
                        subGraph.Edges[edge.EdgeAlias] = edge;
                    }
                    subGraph.IsTailNode[node.Value] = false;
                }
            }

            var graph = new MatchGraph
            {
                ReversedEdgeDict = reversedEdgeDict,
                ConnectedSubGraphs = connectedSubGraphs,
                SourceNodeStatisticsDict = new Dictionary<Tuple<string, bool>, Statistics>(),
            };
            unionFind.Parent = null;

            // When an edge in the MATCH clause is not associated with an alias,
            // assigns to it a default alias: sourceAlias_EdgeColumnName_sinkAlias.
            // Also rewrites edge attributes anywhere in the query that can be bound to this default alias.
            var replaceTableRefVisitor = new ReplaceEdgeReferenceVisitor();
            replaceTableRefVisitor.Invoke(query, edgeColumnToAliasesDict);

            // Rematerializes node tables in the MATCH clause which are defined in the upper-level context
            // and join them with the upper-level table references.
            RematerilizeExtrenalNodeTableReference(query, nodes);

            // Transforms the path reference in the SELECT elements into a
            // scalar function to display path information.
            TransformPathInfoDisplaySelectElement(query, pathDictionary);

            return graph;
        }
        public bool RunTest()
        {
            string[] elements = new string[10] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" };
            UnionFind<string> unionFind = new UnionFind<string>();
            bool success = true;

            // Add in entries
            for (int i = 0; i < 10; i++)
            {
                unionFind.AddElement(elements[i]);
            }

            // Verify that the roots are setup correctly
            for (int i = 0; i < 10; i++)
            {
                success &= unionFind.GetElement(i).Equals(elements[i]);
                Debug.Assert(success);
                success &= unionFind.FindRootIndex(i) == i;
                Debug.Assert(success);
                success &= unionFind.FindRootIndex(elements[i]) == i;
                Debug.Assert(success);
            }

            // Verify that no one is initially connected to anyone else
            for (int i = 1; i < 10; i++)
            {
                success &= !unionFind.AreElementsConnected(i - 1, i);
                Debug.Assert(success);
                success &= !unionFind.AreElementsConnected(elements[i - 1], elements[i]);
                Debug.Assert(success);
            }

            // Union the first half of the nodes together
            for (int i = 1; i < 5; i++)
            {
                unionFind.Union(elements[i - 1], elements[i]);
            }
            // Union the last half of the nodes together
            for (int i = 6; i < 10; i++)
            {
                unionFind.Union(elements[i - 1], elements[i]);
            }

            // Verify that every element in the first half is connected
            // to every other element in the first half
            for (int i = 0; i < 5; i++)
            {
                for (int j = i + 1; j < 5; j++)
                {
                    success &= unionFind.AreElementsConnected(i, j);
                    Debug.Assert(success);
                    success &= unionFind.AreElementsConnected(elements[i], elements[j]);
                    Debug.Assert(success);
                }
            }

            // Verify that every element in the second half is connected
            // to every other element in the second half
            for (int i = 5; i < 10; i++)
            {
                for (int j = i + 1; j < 10; j++)
                {
                    success &= unionFind.AreElementsConnected(i, j);
                    Debug.Assert(success);
                    success &= unionFind.AreElementsConnected(elements[i], elements[j]);
                    Debug.Assert(success);
                }
            }

            // Verify that no element in the first half is connected
            // to any other element in the second half
            for (int i = 0; i < 5; i++)
            {
                for (int j = i + 5; j < 10; j++)
                {
                    success &= !unionFind.AreElementsConnected(i, j);
                    Debug.Assert(success);
                    success &= !unionFind.AreElementsConnected(elements[i], elements[j]);
                    Debug.Assert(success);
                }
            }

            return success;
        }