private static void Program() { int n, m; var input = Console.ReadLine().Split().Select(c => int.Parse(c)).ToArray(); n = input[0]; m = input[1]; Dsu dsu = new Dsu(n); List <Edge> edgeList = new List <Edge>(m); for (int i = 0; i < m; i++) { input = Console.ReadLine().Split().Select(c => int.Parse(c)).ToArray(); edgeList.Add(new Edge(input[0] - 1, input[1] - 1, input[2])); } Int64 result = edgeList .OrderBy(e => e.Weight) .Select(e => (Int64)(dsu.Unite(e.From, e.To) ? e.Weight : 0)) .Sum(); Console.WriteLine(result); }
public IList <IList <string> > AccountsMerge(IList <IList <string> > accounts) { var result = new Dictionary <int, IList <string> >(); var dsu = new Dsu(10001); var emailToName = new Dictionary <string, string>(); var emailToId = new Dictionary <string, int>(); var id = 0; foreach (var account in accounts) { var name = account[0]; for (var i = 1; account.Count > i; ++i) { var email = account[i]; if (!emailToName.ContainsKey(email)) { emailToName.Add(email, name); } if (!emailToId.ContainsKey(email)) { emailToId.Add(email, id++); } dsu.union(emailToId[account[1]], emailToId[email]); } } foreach (var email in emailToName.Keys) { var idx = dsu.find(emailToId[email]); if (result.ContainsKey(idx)) { result[idx].Add(email); } else { result.Add(idx, new List <string> { email }); } } foreach (var idx in result.Keys) { ((List <string>)result[idx]).Sort( (x, y) => string.CompareOrdinal(x, y) ); result[idx].Insert(0, emailToName[result[idx][0]]); } return(result.Values.ToList()); }
public void UnionTest() { var dsu = new Dsu<int>(); dsu.Add(1); dsu.Add(2); dsu.Union(1, 2); Assert.That(dsu.Find(1), Is.EqualTo(dsu.Find(2))); }
public void UnionTest() { var dsu = new Dsu <int>(); dsu.Add(1); dsu.Add(2); dsu.Union(1, 2); Assert.That(dsu.Find(1), Is.EqualTo(dsu.Find(2))); }
public IList <int> NumIslands2(int rows, int cols, int[][] positions) { var n = positions.Length; var result = new int[n]; var grid = new bool[rows, cols]; var dsu = new Dsu(1 + rows * cols); for (var i = 0; rows *cols > i; ++i) { dsu.union(i, rows * cols); } var connectedComponentsCount = 0; for (var i = 0; n > i; ++i) { var row = positions[i][0]; var col = positions[i][1]; if (!grid[row, col]) { var connections = 0; grid[row, col] = true; dsu.setParent(cols * row + col); if (0 < row && grid[row - 1, col]) { connections += dsu.union(cols * (row - 1) + col, cols * row + col)?1:0; } if (0 < col && grid[row, col - 1]) { connections += dsu.union(cols * row - 1 + col, cols * row + col)?1:0; } if (rows > 1 + row && grid[1 + row, col]) { connections += dsu.union(cols * (1 + row) + col, cols * row + col)?1:0; } if (cols > 1 + col && grid[row, 1 + col]) { connections += dsu.union(cols * row + 1 + col, cols * row + col)?1:0; } connectedComponentsCount -= (connections - 1); } result[i] = connectedComponentsCount; } return(result.ToList()); }
public long Solve() { Array.Sort(this.ribs); int result = 0; Dsu dsu = new Dsu(this.n); foreach (Rib rib in this.ribs) { if (dsu.Merge(rib.From, rib.To)) { result += rib.Len; } } return(result); }
/// <summary> /// Исключение подмаршрутов в графе /// </summary> /// <param name="matrix">редуцированная матрица</param> /// <param name="dsu">непересекающиеся множества вершин</param> /// <param name="edges">ребро ветвления, которое уже находяться в маршруте или не входит в него</param> private static void ExcludeSubRoute(ReductionMatrix matrix, Dsu dsu, Digraph.Edge edge) { // если ребро не входит в ветвление if (edge.Begin < 0 || edge.End < 0) // исключение данного ребра из матрицы matrix[Math.Abs(edge.Begin), Math.Abs(edge.End)] = float.PositiveInfinity; // ребро входит в ветвление else { // исключение строки и столбца из матрицы, соответсвующие началу и концу ребра matrix.DeleteRowColumn(edge.Begin, edge.End); // исключение оставщихся подмаршрутов for (int i = 0; i < matrix.Size; i++) for (int j = 0; j < matrix.Size; j++) if (dsu.Find(edge.Begin) == dsu.Find(i) && dsu.Find(edge.End) == dsu.Find(j)) matrix[j, i] = float.PositiveInfinity; // объединение двух вершин графа в одно множество dsu.Union(edge.Begin, edge.End); } }
public bool MoveNext() { // если текущий индекс не находиться в конце списка if (index < iterations.Count) { // текущее изображения берется из списка уже // пройденных на итерациях изображений Current = iterations[index++]; return true; } // иначе определение следующего изображения else { // определение действий на текущей итерациии switch (next) { // остановка метода ветвей и границ case IterationState.Stop: { return false; } // начало метода ветвей и границ case IterationState.Start: { // иницилизация данных dsu = new Dsu(Graph.CountVertex()); min = new Branch(float.PositiveInfinity, null); matrix = new ReductionMatrix(Graph.Adjacency); parent = new Branch(matrix.Reduce(), null); tree = new TreeBranch(Graph, parent); // создание и добавление нового изображения ветвления Current = Painter.Drawing(tree); iterations.Add(Current); // перемещение текущего индекса на конец списка index = iterations.Count; // переход в следующее состояние - левое ветвление метода next = IterationState.LeftBranching; return true; } // левое ветвление метода ветвей и границ case IterationState.LeftBranching: { // определение ребер с нулевой стоимостью var zeroEdges = new List<Digraph.Edge>(); for (int i = 0; i < matrix.Size; i++) for (int j = 0; j < matrix.Size; j++) if (matrix[i, j] == 0) zeroEdges.Add(new Digraph.Edge(i, j, matrix.MinInRow(i, j) + matrix.MinInColumn(j, i))); // если нет ребер ветвления - нет маршрута коммивояжера if (zeroEdges.Count == 0) { TsPath = new Digraph.Path(Graph); // остановка метода ветвей и границ next = IterationState.Stop; return false; } // определение ребра ветвления - ребра с максимальным штрафом edge = zeroEdges.OrderByDescending(e => e.Cost).ToList().First(); // создание левого потомка для данного родителя left = new Branch(parent.LowerBound + edge.Cost, new Digraph.Edge(-edge.Begin, -edge.End, float.PositiveInfinity)); // добавление в дерево ветвлений tree.Add(parent, Branch.Direction.Left, left); // создание и добавление нового изображения ветвления Current = Painter.Drawing(tree); iterations.Add(Current); // перемещение текущего индекса на конец списка index = iterations.Count; // переход в следующее состояние - правое ветвление метода next = IterationState.RightBranching; return true; } // правое ветвление метода case IterationState.RightBranching: { // исключение подмаршрутов для данного ребра ExcludeSubRoute(matrix, dsu, edge); // создание правого потомка для данного родителя right = new Branch(parent.LowerBound + matrix.Reduce(), new Digraph.Edge(edge.Begin, edge.End, Graph[edge.Begin, edge.End])); // добавление в дерево ветвлений tree.Add(parent, Branch.Direction.Right, right); // создание и добавление нового изображения ветвления Current = Painter.Drawing(tree); iterations.Add(Current); // перемещение текущего индекса на конец списка index = iterations.Count; // если размер матрицы достаточно мал if (matrix.RealSize == 2) { // переход в состояние - малый размер матрицы next = IterationState.LittleMatrix; return true; } // выбор новой родительской вершины из еще не подвергшихся ветвлению parent = tree.GetNotGoBranches().OrderBy(b => b.LowerBound).ToList().First(); // проверка на нахождения минимального ветвления и остановки if (min.LowerBound <= parent.LowerBound) { // формирование маршрута коммивояжера TsPath = tree.CreatePathFromBranch(min); // остановка метода next = IterationState.Stop; return false; } // корректировка матрицы для данного ветвления и редуцирование if (parent != right) { // новые непересекающиеся множества вершин dsu = new Dsu(Graph.CountVertex()); // исходная редуцированная матрица matrix = new ReductionMatrix(Graph.Adjacency); // получение текущих вершин для данного ветвления var currentPath = tree.GetEdgesBranching(parent); // исключение всех подмаршрутов foreach (var e in currentPath) ExcludeSubRoute(matrix, dsu, e); // редуцирование матрицы matrix.Reduce(); } // следующая итерация методав ветвей и границ - левое ветвление next = IterationState.LeftBranching; return true; } // малый рамзер матрицы, включение ребер в маршрут case IterationState.LittleMatrix: { // новый родитель parent = right; for (int i = 0; i < matrix.Size && countAdeddEdgeFromMatrix != 1; i++) for (int j = 0; j < matrix.Size && countAdeddEdgeFromMatrix != 1; j++) { if (matrix[i, j] == 0) { // исключение данного ребра из матрицы matrix[i, j] = float.PositiveInfinity; // создание и добавление правого ветвления к родителю right = new Branch(parent.LowerBound, new Digraph.Edge(i, j, Graph[i, j])); tree.Add(parent, Branch.Direction.Right, right); // новый родитель parent = right; // продолжать включать ребра в маршрут на следующей итерации countAdeddEdgeFromMatrix++; } } // если следующая итерация та же if (countAdeddEdgeFromMatrix == 1) { // создание и добавление нового изображения ветвления Current = Painter.Drawing(tree); iterations.Add(Current); // перемещение текущего индекса на конец списка index = iterations.Count; // на следующей итерации будет включено второе ребро countAdeddEdgeFromMatrix++; return true; } else // все ребра включены для данной матрицы countAdeddEdgeFromMatrix = 0; // иначе проверка на новое минимальное ветвление if (parent.LowerBound < min.LowerBound) min = parent; // создание и добавление нового изображения ветвления Current = Painter.Drawing(tree); iterations.Add(Current); // перемещение текущего индекса на конец списка index = iterations.Count; // выбор новой родительской вершины из еще не подвергшихся ветвлению parent = tree.GetNotGoBranches().OrderBy(b => b.LowerBound).ToList().First(); // проверка на нахождения минимального ветвления и остановки if (min.LowerBound <= parent.LowerBound) { // формирование маршрута коммивояжера TsPath = tree.CreatePathFromBranch(min); // остановка метода next = IterationState.Stop; return false; } // корректировка матрицы для данного ветвления и редуцирование if (parent != right) { // новые непересекающиеся множества вершин dsu = new Dsu(Graph.CountVertex()); // исходная редуцированная матрица matrix = new ReductionMatrix(Graph.Adjacency); // получение текущих вершин для данного ветвления var currentPath = tree.GetEdgesBranching(parent); // исключение всех подмаршрутов foreach (var e in currentPath) ExcludeSubRoute(matrix, dsu, e); // редуцирование матрицы matrix.Reduce(); } // следующая итерация методав ветвей и границ - левое ветвление next = IterationState.LeftBranching; return true; } default: return false; } } }
/// <summary> /// Нахождение маршрута коммивояжера /// </summary> /// <param name="graph">ограф. граф</param> /// <returns>маршрут коммивояжера</returns> public static Digraph.Path Tsp(Digraph graph) { // маршрут коммивояжера var TsPath = new Digraph.Path(graph); // если граф пуст if (graph.CountVertex() == 0) { // пустой маршрут return TsPath; } // если граф имеет одну вершину else if (graph.CountVertex() == 1) { TsPath.Append(new Digraph.Edge(0, 0, 0)); // маршрут для одной вершины return TsPath; } // если граф имеет две вершины else if (graph.CountVertex() == 2) { TsPath.Append(new Digraph.Edge(0, 1, graph[0, 1])); TsPath.Append(new Digraph.Edge(1, 0, graph[1, 0])); // маршрут для двух вершин return TsPath; } /// Создания неперекающихся множеств вершин в графе, /// для определения и исключения подмаршрутов графа var dsu = new Dsu(graph.CountVertex()); // минимальное ветвление var minBranch = new Branch(float.PositiveInfinity, null); /// Получение исходной матрицы смежности данного графа var matrix = new ReductionMatrix(graph.Adjacency); /// Создание корня и дерева ветвления var parentBranch = new Branch(matrix.Reduce(), null); var tree = new TreeBranch(graph, parentBranch); for (; ; ) { // ребра с нулевой стоимостью var zeroEdges = new List<Digraph.Edge>(); // Получение всех ребер и соответсвующих штрафов for (int i = 0; i < matrix.Size; i++) for (int j = 0; j < matrix.Size; j++) if (matrix[i, j] == 0) zeroEdges.Add(new Digraph.Edge(i, j, matrix.MinInRow(i, j) + matrix.MinInColumn(j, i))); // если нет ребер ветвления - нет маршрута коммивояжера if (zeroEdges.Count == 0) return new Digraph.Path(graph); /// Определение ребра ветвления - ребра с максимальным штрафом var branchingEdge = zeroEdges.OrderByDescending(e => e.Cost).ToList().First(); /// Процесс ветления - не включая данное ребро var leftBranch = new Branch(parentBranch.LowerBound + branchingEdge.Cost, new Digraph.Edge(-branchingEdge.Begin, -branchingEdge.End, float.PositiveInfinity)); // добавление ветвления в дерево tree.Add(parentBranch, Branch.Direction.Left, leftBranch); /// Процесс ветления - включая данное ребро ExcludeSubRoute(matrix, dsu, branchingEdge); var rightBranch = new Branch(parentBranch.LowerBound + matrix.Reduce(), new Digraph.Edge(branchingEdge.Begin, branchingEdge.End, graph[branchingEdge.Begin, branchingEdge.End])); // добавление ветвления в дерево tree.Add(parentBranch, Branch.Direction.Right, rightBranch); /// Проверка на достаточность размера матрцицы if (matrix.RealSize == 2) { // новый родитель parentBranch = rightBranch; /// Добавление оставщихся ребер в дерево ветвлений for (int i = 0; i < matrix.Size; i++) for (int j = 0; j < matrix.Size; j++) if (matrix[i, j] == 0) { // новый потомок rightBranch = new Branch(parentBranch.LowerBound, new Digraph.Edge(i, j, graph[i, j])); tree.Add(parentBranch, Branch.Direction.Right, rightBranch); // потомок теперь родитель parentBranch = rightBranch; } /// Определение нового минимального ветвления if (parentBranch.LowerBound < minBranch.LowerBound) minBranch = parentBranch; } /// Выбор новой родительской вершины из еще не подвергшихся ветвлению parentBranch = tree.GetNotGoBranches().OrderBy(b => b.LowerBound).ToList().First(); /// Проверка на нахождения минимального ветвления и остановки if (minBranch.LowerBound <= parentBranch.LowerBound) break; /// Корректировка матрицы для данного ветвления и редуцирование if (parentBranch != rightBranch) { // новые непересекающиеся множества вершин dsu = new Dsu(graph.CountVertex()); // исходная редуцированная матрица matrix = new ReductionMatrix(graph.Adjacency); // получение текущих вершин для данного ветвления var currentPath = tree.GetEdgesBranching(parentBranch); // исключение всех подмаршрутов foreach (var e in currentPath) ExcludeSubRoute(matrix, dsu, e); // редуцирование матрицы matrix.Reduce(); } } // формирование маршрута коммивояжера TsPath = tree.CreatePathFromBranch(minBranch); return TsPath; }