private static void CombineUndirectedCyclicGraphs <TKey>(this Node <TKey, UndirectedCyclicGraph <TKey> > node) where TKey : struct { UndirectedCyclicGraph <TKey> firstGraph = node.GraphsThatIncludeThisNode .Cast <UndirectedCyclicGraph <TKey> >().First(); foreach (var graphToCombineFrom in node.GraphsThatIncludeThisNode .Cast <UndirectedCyclicGraph <TKey> >() .Where(n => !n.Equals(firstGraph)) .ToList()) { foreach (var graphsNode in graphToCombineFrom.Nodes.Values) { firstGraph.AddNode(graphsNode); } graphToCombineFrom.ClearNodes(); } }
public long SolveCase(int numOfCities, int numOfRoads, long libCost, long roadCost, IEnumerable <Tuple <int, int> > roads) { var easyCasesResult = CheckEasyCases(numOfCities, numOfRoads, libCost, roadCost, roads); if (easyCasesResult.HasValue) { return(easyCasesResult.Value); } HashSet <UndirectedCyclicGraph <int> > graphs = new HashSet <UndirectedCyclicGraph <int> >(); Node <int, UndirectedCyclicGraph <int> >[] nodes = Enumerable.Range(1, numOfCities).Select(idx => new Node <int, UndirectedCyclicGraph <int> >(idx)).ToArray(); foreach (var road in roads) { var firstNode = nodes[road.Item1 - 1]; var secondNode = nodes[road.Item2 - 1]; if (graphs.Count == 0) { graphs.Add(UndirectedCyclicGraph <int> .CreateNewFromFirstEdge(firstNode, secondNode)); } else { UndirectedCyclicGraph <int> graph = firstNode.GraphsThatIncludeThisNode.FirstOrDefault() as UndirectedCyclicGraph <int> ?? secondNode.GraphsThatIncludeThisNode.FirstOrDefault() as UndirectedCyclicGraph <int>; if (graph == null) { graphs.Add(UndirectedCyclicGraph <int> .CreateNewFromFirstEdge(firstNode, secondNode)); } else { graph.AddEdgeWithNodes(firstNode, secondNode); } } } var nodesWithNoRoads = CombineAllGraphsOf(nodes); return(new HashSet <UndirectedCyclicGraph <int> >(nodes.SelectMany(n => n.GraphsThatIncludeThisNode)) .Sum(graph => roadCost * (graph.Nodes.Count - 1) + libCost) + nodesWithNoRoads * libCost); }