public void UnionTest2() { var dsu = new DSU <int>(); dsu.MakeSet(1); dsu.MakeSet(2); dsu.MakeSet(3); dsu.MakeSet(4); dsu.MakeSet(5); Assert.AreEqual(4, dsu.Find(4)); dsu.Unite(1, 4, isRandom: false); dsu.Unite(3, 5, isRandom: false); Assert.AreEqual(1, dsu.Find(4)); Assert.AreEqual(1, dsu.Find(1)); Assert.AreEqual(2, dsu.Find(2)); Assert.AreEqual(3, dsu.Find(5)); Assert.AreEqual(3, dsu.Find(3)); dsu.Unite(5, 2, isRandom: false); Assert.AreEqual(3, dsu.Find(5)); Assert.AreEqual(3, dsu.Find(3)); Assert.AreEqual(3, dsu.Find(2)); }
public static void Main() { Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false }); int n = NextInt; int q = NextInt; DSU dsu = new DSU(n); for (int i = 0; i < q; i++) { var t = NextInt; var u = NextInt; var v = NextInt; if (t == 0) { dsu.Merge(u, v); } if (t == 1) { Console.WriteLine(dsu.Same(u, v) ? "1" : "0"); } } Console.Out.Flush(); }
static void Main() { string[] lines = File.ReadAllLines("dsu.in"); int n = int.Parse(lines[0]); DSU dsu = new DSU(); for (int i = 1; i <= n; ++i) dsu.AddSingleItem(i); StreamWriter sw = new StreamWriter("dsu.out"); foreach (string s in lines.Skip(1)) { string[] parts = s.Split(' '); if (parts[0] == "union") { int a = int.Parse(parts[1]) - 1, b = int.Parse(parts[2]) - 1; dsu.Union(a,b); } else if (parts[0] == "get") { int a = int.Parse(parts[1]) - 1; DSU.DsuSet x = dsu.Get(a); sw.WriteLine("{0} {1} {2}", x.Min, x.Max, x.Count); } } sw.Close(); }
// https://leetcode.com/problems/regions-cut-by-slashes/solution/ public int RegionsBySlashes(string[] grid) { int N = grid.Length; DSU dsu = new DSU(4 * N * N); for (int r = 0; r < N; ++r) { for (int c = 0; c < N; ++c) { int root = 4 * (r * N + c); char val = grid[r][c]; if (val != '\\') { dsu.union(root + 0, root + 1); dsu.union(root + 2, root + 3); } if (val != '/') { dsu.union(root + 0, root + 2); dsu.union(root + 1, root + 3); } if (r + 1 < N) { dsu.union(root + 3, (root + 4 * N) + 0); } if (r - 1 >= 0) { dsu.union(root + 0, (root - 4 * N) + 3); } if (c + 1 < N) { dsu.union(root + 2, (root + 4) + 1); } if (c - 1 >= 0) { dsu.union(root + 1, (root - 4) + 2); } } } int ans = 0; for (int x = 0; x < 4 * N * N; ++x) { if (dsu.find(x) == x) { ans++; } } return(ans); }
public IList <IList <string> > AccountsMerge(IList <IList <string> > accounts) { DSU dsu = new DSU(); var emailToName = new Dictionary <string, string>(); var emailToID = new Dictionary <string, int>(); int id = 0; foreach (IList <string> account in accounts) { string name = ""; foreach (string email in account) { if (name == "") { name = email; continue; } emailToName.Add(email, name); if (!emailToID.ContainsKey(email)) { emailToID.Add(email, id++); } dsu.union(emailToID.GetValueOrDefault(account[1]), emailToID.GetValueOrDefault(email)); } } var ans = new Dictionary <int, List <string> >(); foreach (string email in emailToName.Keys) { int index = dsu.find(emailToID.GetValueOrDefault(email)); if (!ans.ContainsKey(index)) { var dd = new List <string>(); dd.Add(email); ans.Add(index, dd); } } foreach (IList <string> component in ans.Values) { _ = component.OrderBy(x => x); component.Add(emailToName.GetValueOrDefault(component[0])); } // getting the return data IList <IList <string> > output = new List <IList <string> >(); foreach (var d in ans.Values) { if (!output.Contains(d)) { output.Add(d); } } return(output); }
public void UnionTest() { var dsu = new DSU <int>(); dsu.MakeSet(1); dsu.MakeSet(2); dsu.Unite(1, 2, isRandom: false); Assert.That(dsu.Find(1), Is.EqualTo(dsu.Find(2))); }
/// <summary> /// Nov. 19, 2020 /// Union find algorithm /// study code /// https://leetcode.com/problems/sentence-similarity-ii/solution/ /// Time complexity: /// Time Complexity: O(N log P + P), where N is the maximum length of words1 and words2, /// and P is the length of pairs. If we used union-by-rank, this complexity improves to /// O(N * a(P) + P), close to O(N + P), where α is the Inverse-Ackermann function. /// </summary> /// <param name="words1"></param> /// <param name="words2"></param> /// <param name="pairs"></param> /// <returns></returns> public bool AreSentencesSimilarTwo(string[] words1, string[] words2, IList <IList <string> > pairs) { var length1 = words1.Length; var length2 = words2.Length; var pLength = pairs.Count; if (length1 != length2) { return(false); } // index -> indexMap better name? var indexMap = new Dictionary <string, int>(); int count = 0; var dsu = new DSU(2 * pLength); foreach (var pair in pairs) { // go through two words in one pair foreach (var p in pair) { if (!indexMap.ContainsKey(p)) { indexMap.Add(p, count++); } } dsu.Union(indexMap[pair[0]], indexMap[pair[1]]); } for (int i = 0; i < length1; ++i) { var w1 = words1[i]; var w2 = words2[i]; if (w1.CompareTo(w2) == 0) { continue; } if (!indexMap.ContainsKey(w1) || !indexMap.ContainsKey(w2) || dsu.Find(indexMap[w1]) != dsu.Find(indexMap[w2])) { return(false); } } return(true); }
public int[] FindRedundantConnection2(int[][] edges) { DSU = new DSU(edges.Length + 1); foreach (int[] edge in edges) { if (DSU.Union(edge[0], edge[1])) { return(edge); } } return(edges[0]); }
private int[] FindRedundantConnection(int[][] edges) { DSU dsu = new DSU(edges.Length); foreach (int[] edge in edges) { if (!dsu.Union(edge[0], edge[1])) { return(edge); } } throw new ArgumentException("Invalid argument"); }
public int[] FindRedundantConnection(int[,] edges) { //1 定义图, list<int> 的数组, 坐标是起点, 数组是neighbor DSU dsu = new DSU(MAX_EDGE_VAL + 1); for (int i = 0; i < edges.GetLength(0); i++) { if (!dsu.union(edges[i, 0], edges[i, 1])) { return new[] { edges[i, 0], edges[i, 1] } } ; } return(null); }
public int RemoveStones(int[][] stones) { var dsu = new DSU(20000); foreach (var stone in stones) { dsu.Union(stone[0], stone[1] + 10000); } var seen = new HashSet <int>(); foreach (var stone in stones) { seen.Add(dsu.Find(stone[0])); } return(stones.Length - seen.Count); }
public static void Main() { Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false }); int n = NextInt; int q = NextInt; UnionFind uf = new UnionFind(n); DSU dsu = new DSU(n); void VerifyGroup() { var groups = dsu.Groups().ToArray().Select(x => x.OrderBy(x => x).ToArray()).OrderBy(x => x.First()).ToArray(); var ans = Enumerable.Range(0, n).GroupBy(uf.Find).Select(x => x.OrderBy(x => x).ToArray()).OrderBy(x => x.First()).ToArray(); if (groups.Length != ans.Length) { throw new Exception(); } if (groups.Zip(ans, (x, y) => x.SequenceEqual(y)).Any(x => !x)) { throw new Exception(); } } for (int i = 0; i < q; i++) { var(t, u, v) = (NextInt, NextInt, NextInt); if (t == 0) { dsu.Merge(u, v); uf.TryUnite(u, v); } else { Console.WriteLine(dsu.Same(u, v) ? "1" : "0"); } if ((i & -i) == 0) { VerifyGroup(); } } VerifyGroup(); Console.Out.Flush(); }
private int MinCostToConnectNodes(int N, int[][] connections) { Array.Sort(connections, (a, b) => a[2] - b[2]); DSU dsu = new DSU(N + 1); int cost = 0; foreach (int[] arr in connections) { if (!dsu.Union(arr[0], arr[1])) { cost += arr[2]; } } return(dsu.Count == 2 ? cost : -1); }
// https://leetcode.com/problems/most-stones-removed-with-same-row-or-column/discuss/239162/DFS-Time-O(N)-Space-O(N)-ConciseandandReadable // https://leetcode.com/problems/most-stones-removed-with-same-row-or-column/solution/ public int removeStones(int[][] stones) { DSU dsu = new DSU(20000); HashSet <int> seen = new HashSet <int>(); foreach (var stone in stones) { dsu.union(stone[0], stone[1] + 10000); } foreach (var stone in stones) { seen.Add(dsu.find(stone[0])); } return(stones.Length - seen.Count()); }
public BotProgram Optimize(Model3D modelToBuild) { _modelToBuild = modelToBuild; _treeToConstruct = _modelToBuild.ToOctoTree(); _scene = Scene.New(_modelToBuild.Resolution); _program = new BotProgram(); _resolution = _modelToBuild.Resolution; _resolutionSquared = _resolution * _resolution; _dsu = new DSU(_resolutionSquared * _resolution + 1); _voxelsFilled = 0; // Console.WriteLine("Starting to optimize..."); OptimizeInternal(); return(_program); }
public override IEnumerable <object> Solve(TextReader inputStream) { var(n, queries) = inputStream.ReadValue <int, int>(); var dsu = new DSU(n); for (int q = 0; q < queries; q++) { var(t, u, v) = inputStream.ReadValue <int, int, int>(); if (t == 0) { dsu.Merge(u, v); } else { yield return(dsu.Same(u, v) ? 1 : 0); } } }
public static void Solve() { var(N, Q) = Scanner.Scan <int, int>(); var dsu = new DSU(N); for (var i = 0; i < Q; i++) { var(t, u, v) = Scanner.Scan <int, int, int>(); if (t == 0) { dsu.Merge(u, v); } else { Console.WriteLine(dsu.IsSame(u, v) ? 1 : 0); } } }
public IList <int> NumIslands2(int rows, int cols, int[,] positions) { var dsu = new DSU(rows * cols); var result = new List <int>(); int GetIndx(int r, int c) => r * cols + c; for (var i = 0; i < positions.GetLength(0); i++) { var r = positions[i, 0]; var c = positions[i, 1]; var indx = GetIndx(r, c); dsu.Set(indx); var up = GetIndx(r - 1, c); if (r - 1 >= 0 && dsu.IsSet(up)) { dsu.Union(indx, up); } var down = GetIndx(r + 1, c); if (r + 1 < rows && dsu.IsSet(down)) { dsu.Union(indx, down); } var left = GetIndx(r, c - 1); if (c - 1 >= 0 && dsu.IsSet(left)) { dsu.Union(indx, left); } var right = GetIndx(r, c + 1); if (c + 1 < cols && dsu.IsSet(right)) { dsu.Union(indx, right); } result.Add(dsu.GetCount()); } return(result); }
public void Solve(ConsoleReader cr, ConsoleWriter cw) { int n = cr; int q = cr; var dsu = new DSU(n); for (int i = 0; i < q; i++) { int t = cr; int u = cr; int v = cr; if (t == 0) { dsu.Merge(u, v); } else { cw.WriteLine(dsu.Same(u, v) ? 1 : 0); } } }
public bool AreSentencesSimilarTwo(string[] words1, string[] words2, string[,] pairs) { if (words1.Length != words2.Length) { return(false); } Dictionary <string, int> index = new Dictionary <string, int>(); int count = 0; DSU dsu = new DSU(2 * pairs.GetLength(0)); for (int i = 0; i < pairs.GetLength(0); i++) { if (!index.ContainsKey(pairs[i, 0])) { index[pairs[i, 0]] = count++; } if (!index.ContainsKey(pairs[i, 1])) { index[pairs[i, 1]] = count++; } dsu.union(index[pairs[i, 0]], index[pairs[i, 1]]); } for (int i = 0; i < words1.Length; ++i) { String w1 = words1[i], w2 = words2[i]; if (w1.Equals(w2)) { continue; } if (!index.ContainsKey(w1) || !index.ContainsKey(w2) || dsu.find(index[w1]) != dsu.find(index[w2])) { return(false); } } return(true); }
public static void Solve() { var(N, M, K) = Scanner.Scan <int, int, int>(); var friends = new List <int> [N].Select(x => new List <int>()).ToArray(); var blocks = new List <int> [N].Select(x => new List <int>()).ToArray(); var dsu = new DSU(N); for (var i = 0; i < M; i++) { var(A, B) = Scanner.Scan <int, int>(); dsu.Merge(--A, --B); friends[A].Add(B); friends[B].Add(A); } for (var i = 0; i < K; i++) { var(C, D) = Scanner.Scan <int, int>(); blocks[--C].Add(--D); blocks[D].Add(C); } var answer = new int[N]; for (var i = 0; i < N; i++) { answer[i] = dsu.SizeOf(i) - friends[i].Count - 1; foreach (var block in blocks[i]) { if (dsu.IsSame(i, block)) { answer[i]--; } } } Console.WriteLine(string.Join(" ", answer)); }
public int[] HitBricks(int[][] grid, int[][] hits) { int R = grid.Length, C = grid[0].Length; int[] dr = { 1, 0, -1, 0 }; int[] dc = { 0, 1, 0, -1 }; var A = new int[R][]; for (int r = 0; r < R; ++r) { A[r] = (int[])grid[r].Clone(); } foreach (int[] hit in hits) { A[hit[0]][hit[1]] = 0; } DSU dsu = new DSU(R * C + 1); //建立 DSU for (int r = 0; r < R; ++r) { for (int c = 0; c < C; ++c) { if (A[r][c] == 1) //如果是砖 { int i = r * C + c; // 二维坐标转1维 if (r == 0) //如果是最上层 { dsu.union(i, R * C); //R*C 默认是 最上层吧 } if (r > 0 && A[r - 1][c] == 1) { dsu.union(i, (r - 1) * C + c); //和上面的连 } if (c > 0 && A[r][c - 1] == 1) { dsu.union(i, r * C + c - 1);//和左面的连 } } } } int t = hits.Length; int[] ans = new int[t--]; while (t >= 0) { int r = hits[t][0]; int c = hits[t][1]; int preRoof = dsu.top(); if (grid[r][c] == 0) { t--; } else { int i = r * C + c; for (int k = 0; k < 4; ++k) { int nr = r + dr[k]; int nc = c + dc[k]; if (0 <= nr && nr < R && 0 <= nc && nc < C && A[nr][nc] == 1) { dsu.union(i, nr * C + nc); } } if (r == 0) { dsu.union(i, R * C); } A[r][c] = 1; ans[t--] = Math.Max(0, dsu.top() - preRoof - 1); } } return(ans); }
public IList <IList <string> > AccountsMerge(IList <IList <string> > accounts) { EmailToId = new Dictionary <string, int>(); EmailToName = new Dictionary <string, string>(); foreach (var account in accounts) { if (account.Count < 2) { continue; } var name = account[0]; for (var i = 1; i < account.Count; i++) { if (!EmailToId.ContainsKey(account[i])) { var id = EmailToId.Count; EmailToId[account[i]] = id; EmailToName[account[i]] = name; } } } var totalAccounts = EmailToId.Count; DSU = new DSU(totalAccounts); foreach (var account in accounts) { // var name = account[0]; for (var i = 1; i < account.Count - 1; i++) { var id1 = EmailToId[account[i]]; var id2 = EmailToId[account[i + 1]]; if (id1 != id2) { DSU.Union(id1, id2); } } } var result = new Dictionary <int, List <string> >(); foreach (var email in EmailToName.Keys) { int index = DSU.Find(EmailToId[email]); if (result.TryGetValue(index, out var list)) { list.Add(email); } else { result[index] = new List <string> { email }; } } foreach (var emails in result.Values) { emails.Sort((x, y) => { var i = 0; while (i < x.Length && i < y.Length) { if (x[i] != y[i]) { return(x[i].CompareTo(y[i])); } i++; } return(x.Length.CompareTo(y.Length)); }); emails.Insert(0, EmailToName[emails[0]]); } return(result.Values.ToList <IList <string> >()); }
private static bool Prefix(Thing __instance) { if (Find.CameraDriver.CurrentZoom != CameraZoomRange.Closest) { return(true); // maybe someone changes this? Who knows. } if (!(__instance is Building_Storage DSU)) { return(true); } var cds = DSU.GetComp <CompDeepStorage>(); if (cds == null) { return(true); } switch (cds.cdsProps.overlayType) { case GuiOverlayType.Normal: return(true); case GuiOverlayType.None: return(false); } List <Thing> things; string s; switch (cds.cdsProps.overlayType) { case GuiOverlayType.CountOfAllStacks: { // maybe Armor Racks, Clothing Racks, def Weapon Lockers etc... things = new List <Thing>(); foreach (var c in DSU.AllSlotCellsList()) { things.AddRange(__instance.Map.thingGrid.ThingsListAtFast(c).FindAll(t => t.def.EverStorable(false))); } switch (things.Count) { case 0 when cds.cdsProps.showContents: return(false); // If it's empty, player will see! case 0: s = "LWM_DS_Empty".Translate(); break; case 1: s = 1.ToStringCached(); // Why not s="1";? You never know, someone may be playing in... break; default: { if (AllSameType(things)) { s = "x" + things.Count.ToStringCached(); } else { s = "[ " + things.Count.ToStringCached() + " ]"; } break; } } GenMapUI.DrawThingLabel(GenMapUI.LabelDrawPosFor(__instance, 0f), s, GenMapUI.DefaultThingLabelColor); return(false); } case GuiOverlayType.CountOfStacksPerCell: { // maybe Armor Racks, Clothing Racks? foreach (var c in DSU.AllSlotCellsList()) { things = __instance.Map.thingGrid.ThingsListAtFast(c).FindAll(t => t.def.EverStorable(false)); switch (things.Count) { case 0 when cds.cdsProps.showContents: continue; // if it's empty, player will see! case 0: s = "LWM_DS_Empty".Translate(); break; case 1: s = 1.ToStringCached(); // ..a language that doesn't use arabic numerals? break; default: { if (AllSameType(things)) { s = "x" + things.Count.ToStringCached(); } else { s = "[ " + things.Count.ToStringCached() + " ]"; } break; } } var l2 = GenMapUI.LabelDrawPosFor(c); // l2.x+=cds.x; // l2.y+=cds.y; l2.y += 10f; GenMapUI.DrawThingLabel(l2, s, GenMapUI.DefaultThingLabelColor); } return(false); } case GuiOverlayType.SumOfAllItems: { // probably food baskets, skips, etc... things = new List <Thing>(); foreach (var c in DSU.slotGroup.CellsList) { things.AddRange(__instance.Map.thingGrid.ThingsListAtFast(c) .FindAll(t => t.def.EverStorable(false))); } if (things.Count == 0) { if (cds.cdsProps.showContents) { return(false); // if it's empty, player will see } s = "LWM_DS_Empty".Translate(); } else { var count = things[0].stackCount; var allTheSame = true; for (var i = 1; i < things.Count; i++) { if (things[i].def != things[0].def) { allTheSame = false; } count += things[i].stackCount; } if (allTheSame) { s = count.ToStringCached(); } else { s = "[ " + count.ToStringCached() + " ]"; } } GenMapUI.DrawThingLabel(GenMapUI.LabelDrawPosFor(__instance, 0f), s, GenMapUI.DefaultThingLabelColor); return(false); } case GuiOverlayType.SumOfItemsPerCell: { // Big Shelves var anyItems = false; var itemsWithStackSizeOne = false; foreach (var c in DSU.AllSlotCellsList()) { things = __instance.Map.thingGrid.ThingsListAtFast(c).FindAll(t => t.def.EverStorable(false)); if (things.Count > 0) { anyItems = true; var count = 0; foreach (var t in things) { if (itemsWithStackSizeOne || t.def.stackLimit == 1) { itemsWithStackSizeOne = true; if (things.Count == 1) { s = 1.ToStringCached(); // ..a language that doesn't use arabic numerals? } else if (AllSameType(things)) { s = "x" + things.Count.ToStringCached(); } else { s = "[ " + things.Count.ToStringCached() + " ]"; } var l = GenMapUI.LabelDrawPosFor(c); l.y += 10f; GenMapUI.DrawThingLabel(l, s, GenMapUI.DefaultThingLabelColor); goto WhyDoesCSharpNotHaveBreakTwo; } else { count += t.stackCount; } } if (AllSameType(things)) { s = count.ToStringCached(); } else { s = "[ " + count.ToStringCached() + " ]"; } var l2 = GenMapUI.LabelDrawPosFor(c); l2.y += 10f; GenMapUI.DrawThingLabel(l2, s, GenMapUI.DefaultThingLabelColor); } // if count > 0 WhyDoesCSharpNotHaveBreakTwo :; } // foreach cell if (anyItems || cds.cdsProps.showContents) { return(false); } // there are no items, but no way to see that. s = "LWM_DS_Empty".Translate(); GenMapUI.DrawThingLabel(GenMapUI.LabelDrawPosFor(__instance, 0f), s, GenMapUI.DefaultThingLabelColor); return(false); } default: Log.Warning("LWM DeepStorage: could not find GuiOverlayType of " + cds.cdsProps.overlayType); return(true); } }