Пример #1
0
        public void QuickUnionTest()
        {
            QuickUnion uf = new QuickUnion(13);

            uf.Union(0, 1);
            uf.Union(1, 2);
            uf.Union(4, 5);
            uf.Union(0, 3);
            uf.Union(7, 8);
            uf.Union(8, 9);
            uf.Union(6, 11);
            uf.Union(11, 10);
            uf.Union(9, 12);
            uf.Union(1, 12);

            Assert.False(uf.IsConnected(2, 5));
            Assert.True(uf.IsConnected(7, 12));
            Assert.False(uf.IsConnected(6, 8));
            Assert.True(uf.IsConnected(0, 12));
        }
Пример #2
0
        public void Union_ConnectTwoElements_Should_BeConnected()
        {
            // Arrange
            var qf = new QuickUnion(10);

            // Act
            qf.Union(1, 2);

            // Assert
            Assert.True(qf.Connected(1, 2));
        }
Пример #3
0
        public void QuickFind_TinyFile_True()
        {
            var dots       = new Dots(@"DataStore\tinyUF.txt");
            var quickUnion = new QuickUnion(dots.Count);

            foreach (Tuple <int, int> item in dots.Items)
            {
                if (quickUnion.Connected(item.Item1, item.Item2))
                {
                    continue;
                }
                quickUnion.Union(item.Item1, item.Item2);
            }
            Assert.Equal(2, quickUnion.Count);
        }
Пример #4
0
        public int SolveMSt()
        {
            int mstCost = 0;

            _MstEdges = new List <Edge>();
            QuickUnion Qu = new QuickUnion(_nodes + 1);

            Array.Sort(_EdgeCost, _EdgeList);
            for (int i = 0; i < _EdgeCost.Length; i++)
            {
                if (!Qu.Find(_EdgeList[i].a, _EdgeList[i].b))
                {
                    mstCost += _EdgeCost[i];
                    _MstEdges.Add(_EdgeList[i]);
                    Qu.Union(_EdgeList[i].a, _EdgeList[i].b);
                }
            }

            return(mstCost);
        }
Пример #5
0
    public void TestQuickUnion()
    {
        var input = new List <int[]>()
        {
            new int[] { 1, 3 },
            new int[] { 1, 4 },
            new int[] { 8, 9 }
        };

        var N = 10;

        var uf = new QuickUnion(N);

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

        Assert.Equal(uf.Connected(3, 4), true);
        Assert.Equal(uf.Connected(9, 0), false);
    }
        public static int GetMaximumGroup(IList <int[]> pairs, int n)
        {
            if (n <= 0 || pairs == null || pairs.Count == 0)
            {
                return(-1);
            }

            var unionFind = new QuickUnion(n);

            foreach (var item in pairs)
            {
                unionFind.Union(item[0], item[1]);
            }

            var groupCount = new Dictionary <int, int>();

            // quick find and also path compression
            for (int i = 0; i < n; i++)
            {
                unionFind.QuickFindAndPathCompression(i);
            }

            // Find maximum group number
            for (int i = 0; i < n; i++)
            {
                var rootId = unionFind.QuickFind(i);
                if (!groupCount.ContainsKey(rootId))
                {
                    groupCount.Add(rootId, 1);
                }
                else
                {
                    groupCount[rootId]++;
                }
            }

            return(groupCount.Values.Max());
        }
Пример #7
0
        /// <summary>
        /// assume that maximum number of cities is 50
        /// Map new road as integer quickly.
        /// using SortedDictionary
        /// https://github.com/jianminchen/Leetcode_Julia/blob/master/source%20code/23%20Merge%20K%20sorted%20lists%20-%20using%20minimum%20heap.cs
        /// </summary>
        /// <param name="noCities"></param>
        /// <param name="existingRoads"></param>
        /// <param name="newRoads"></param>
        /// <param name="roadWithCost"></param>
        /// <returns></returns>
        public static int getMinimumCost(
            int noCities,
            List <int[]> existingRoads,
            int newRoads,
            List <int[]> roadWithCost)
        {
            var quickUnion = new QuickUnion(noCities);

            foreach (var item in existingRoads)
            {
                // adjust the value of id from 0 to N - 1
                quickUnion.Union(item[0] - 1, item[1] - 1);
            }

            int count = quickUnion.GetCount();

            var newRoadMap = new SortedDictionary <int, Queue <int[]> >();

            foreach (int[] item in roadWithCost)
            {
                var id1      = item[0] - 1;
                var id2      = item[1] - 1;
                var roadCost = item[2];

                if (!newRoadMap.ContainsKey(roadCost))
                {
                    newRoadMap.Add(roadCost, new Queue <int[]>());
                }

                newRoadMap[roadCost].Enqueue(new int[] { id1, id2 });
            }

            var totalCost = 0;

            while (newRoadMap.Count > 0)
            {
                int minCost = newRoadMap.First().Key;
                var ids     = newRoadMap[minCost].Dequeue();

                if (newRoadMap[minCost].Count == 0)
                {
                    newRoadMap.Remove(minCost);
                }

                var id1 = ids[0];
                var id2 = ids[1];

                var connected = quickUnion.Connected(id1, id2);
                if (connected)
                {
                    continue;
                }

                totalCost += minCost;
                quickUnion.Union(id1, id2); // Union, not Connected

                if (quickUnion.GetCount() == 1)
                {
                    break;
                }
            }

            if (quickUnion.GetCount() > 1)
            {
                return(-1);
            }

            return(totalCost);
        }
        /// <summary>
        /// Leetcode 721
        /// https://leetcode.com/problems/accounts-merge/
        /// </summary>
        /// <param name="accounts"></param>
        /// <returns></returns>
        public static IList <IList <string> > AccountsMerge(IList <IList <string> > accounts)
        {
            var emailSet = getAllEmails(accounts);

            // https://leetcode.com/problems/accounts-merge/discuss/164699/C-Solution-(Union-Find)-beats-91.49
            var emailList = emailSet.ToList();

            var ordCmp = StringComparer.Ordinal;

            emailList.Sort(ordCmp);

            var emailNameMap = getEmailNameMap(accounts);
            var emailIdmap   = new Dictionary <string, int>();

            int index       = 0;
            var emailLookup = new List <string>();

            foreach (var item in emailList)
            {
                emailIdmap.Add(item, index);
                index++;
                emailLookup.Add(item);
            }

            var unionFind = new QuickUnion(emailSet.Count);

            unionFind.EmailIdMap = emailIdmap;

            foreach (var list in accounts)
            {
                for (int i = 1; i < list.Count - 1; i++)
                {
                    var email1 = list[i];
                    var email2 = list[i + 1];

                    var connected = unionFind.Connected(email1, email2);
                    if (!connected)
                    {
                        unionFind.Union(email1, email2);
                    }
                }
            }

            // flat the tree
            for (int i = 0; i < emailSet.Count; i++)
            {
                unionFind.QuickFindAndPathCompression(i);
            }

            var dict   = new Dictionary <int, List <string> >();
            var parent = unionFind.GetParent();

            for (int i = 0; i < parent.Length; i++)
            {
                var key = parent[i];
                if (!dict.ContainsKey(key))
                {
                    dict.Add(key, new List <string>());
                }

                dict[key].Add(emailLookup[i]);
            }

            // output a list
            var result = new List <IList <string> >();

            foreach (var item in dict.Keys)
            {
                var list  = new List <string>();
                var email = emailLookup[item];
                var name  = emailNameMap[email];

                list.Add(name);

                var values = dict[item];
                list.AddRange(values);

                result.Add(list);
            }

            return(result);
        }
        /// <summary>
        /// assume that maximum number of cities is 50
        /// Map new road as integer quickly.
        /// </summary>
        /// <param name="noCities"></param>
        /// <param name="existingRoads"></param>
        /// <param name="newRoads"></param>
        /// <param name="roadWithCost"></param>
        /// <returns></returns>
        public static int getMinimumCost(
            int noCities,
            List <int[]> existingRoads,
            int newRoads,
            List <int[]> roadWithCost)
        {
            var quickUnion = new QuickUnion(noCities);

            foreach (var item in existingRoads)
            {
                // adjust the value of id from 0 to N - 1
                quickUnion.Union(item[0] - 1, item[1] - 1);
            }

            int count = quickUnion.GetCount();

            var newRoadMap = new Dictionary <int, List <int> >();

            foreach (int[] item in roadWithCost)
            {
                var id1      = item[0] - 1;
                var id2      = item[1] - 1;
                var roadCost = item[2];

                var newId = id1 * 50 + id2;
                if (!newRoadMap.ContainsKey(roadCost))
                {
                    newRoadMap.Add(roadCost, new List <int>());
                }

                newRoadMap[roadCost].Add(newId);
            }

            var costs = newRoadMap.Keys.ToArray();

            Array.Sort(costs);

            var length    = costs.Length;
            var totalCost = 0;

            for (int i = 0; i < length; i++)
            {
                var current = costs[i];
                var ids     = newRoadMap[current];
                foreach (var id in ids)
                {
                    var id1 = id % 50;
                    var id2 = id / 50;

                    var connected = quickUnion.Connected(id1, id2);
                    if (connected)
                    {
                        continue;
                    }

                    totalCost += current;
                    quickUnion.Union(id1, id2); // Union, not Connected
                }
            }

            if (quickUnion.GetCount() > 1)
            {
                return(-1);
            }

            return(totalCost);
        }
        public void TestingUFQuickUnion()
        {
            var unionFind = new QuickUnion(10);

            unionFind.Union(4, 3);
            unionFind.Union(3, 8);
            unionFind.Union(6, 5);
            unionFind.Union(9, 4);
            unionFind.Union(2, 1);
            unionFind.Union(8, 9);
            unionFind.Union(5, 0);
            unionFind.Union(7, 2);
            unionFind.Union(6, 1);
            unionFind.Union(1, 0);
            unionFind.Union(6, 7);
        }