public IGraph Build()
        {
            var lines = File.ReadAllLines(_file);

            var nodes = new Node[lines.Length + 1]; //+1 since nodes are 1 based
            var edges = new List<Edge>(lines.Length);
            var edgeId = 0;

            foreach (var line in lines)
            {
                var dataitems = line.Split(_seperator, StringSplitOptions.RemoveEmptyEntries);
                var left = Int32.Parse(dataitems[0]);
                var right = Int32.Parse(dataitems[1]);

                if (nodes[left] == null) nodes[left] = new Node(left);
                if (nodes[right] == null) nodes[right] = new Node(right);

                nodes[left].Outgoing.Add(nodes[right]);
                nodes[right].Incoming.Add(nodes[left]);

                var edge = new Edge(++edgeId, nodes[left], nodes[right], EdgeDirection.LeftToRight);
                edges.Add(edge);
            }

            var finalNodes = new List<Node>(nodes.Where(n => n != null));
            return new Graph2(finalNodes, edges);
        }
        public IList<Node> SelectNotVisitedNodes(Node startingNode)
        {
            var neighbors = Edges
                      .Where(e => (e.Left == startingNode && (e.Direction == EdgeDirection.None || e.Direction == EdgeDirection.LeftToRight)) ||
                                  (e.Right == startingNode && (e.Direction == EdgeDirection.None || e.Direction == EdgeDirection.RightToLeft)))
                      .Select(n => n.Left == startingNode ? n.Right : n.Left)
                      .Where(n => !n.Visited);

            return neighbors.ToList();
        }
 public IList<Node> SelectNotVisitedNodes(Node startingNode)
 {
     if (_currentDirection == EdgeDirection.LeftToRight)
     {
         //todo: select outgoing edges where not visited
         return startingNode.Outgoing.Where(n => !n.Visited).ToList();
     }
     //todo: select incoming edges not visited
     return startingNode.Incoming.Where(n => !n.Visited).ToList();
 }
        public void Execute(Node startingNode)
        {
            startingNode.Visited = true;

            var neighbors = _graph.SelectNotVisitedNodes(startingNode);

            foreach (var neighbor in neighbors)
            {
                if(!neighbor.Visited) Execute(neighbor);
            }

            startingNode.Sort = _sortCounter--;
        }
        private void Dfs(Node startingNode)
        {
            _sccSizeCounter++;
            startingNode.Visited = true;

            var neighbors = _graph.SelectNotVisitedNodes(startingNode);

            foreach (var neighbor in neighbors)
            {
                if (!neighbor.Visited) Dfs(neighbor);
            }

            startingNode.Sort = _finishTimeCounter++;
        }
        private void Dfs(Node startingNode, bool accumulate = false)
        {
            startingNode.Visited = true;

            var neighbors = _graph.SelectNotVisitedNodes(startingNode);
            if (accumulate) _sccNodes[_sccIndexer].UnionWith(neighbors.Select(n => n.Label));

            foreach (var neighbor in neighbors)
            {
                if (!neighbor.Visited) Dfs(neighbor, accumulate);
            }

            startingNode.Sort = _finishTimeCounter++;
        }
        public IGraph Build()
        {
            var lines = File.ReadAllLines(_file);

            var nodes = new Node[lines.Length + 1]; //since nodes are 1 based
            var edges = new List<Edge>();
            var edgeId = 0;

            foreach (var line in lines)
            {
                var dataitems = line.Split(_seperator, StringSplitOptions.RemoveEmptyEntries);

                var label = Int32.Parse(dataitems[0]);

                var left = nodes[label];
                if (left == null)
                {
                    left = new Node(label);
                    nodes[label] = left;
                }

                foreach (var item in dataitems.Skip(1))
                {
                    var values = item.Split(_edgeSeperator);

                    var itemLabel = Int32.Parse(values[0]);
                    var itemWeight = Int32.Parse(values[1]);

                    var right = nodes[itemLabel];
                    if (right == null)
                    {
                        right = new Node(itemLabel);
                        nodes[itemLabel] = right;
                    }

                    //undirected, no paralle, so no need to add edge if left > right as it should already be added
                    if (left.Label > right.Label) continue;

                    var edge = new Edge(++edgeId, left, right, EdgeDirection.None, itemWeight);
                    edges.Add(edge);
                }
            }

            var finalNodes = nodes.Where(n => n != null).ToList();
            return new Graph(finalNodes, edges);
        }
        private static int Min(int[] previousColumn, Node node)
        {
            var min = previousColumn[node.Label];

            var incomingEdges = node.IncomingEdges;

            foreach (var incomingEdge in incomingEdges)
            {
                var prefixWeight = previousColumn[incomingEdge.Left.Label];
                if (prefixWeight == int.MaxValue) continue;

                var newCost = prefixWeight + incomingEdge.Weight;
                if (newCost < min) min = newCost;
            }

            return min;
        }
        public IGraph Build()
        {
            var nodes = new List<Node>();
            var edges = new List<Edge>();
            int edgeId = 0;

            var lines = File.ReadAllLines(_file);
            foreach (var line in lines)
            {
                var dataitems = line.Split(_seperator, StringSplitOptions.RemoveEmptyEntries);

                var label = Int32.Parse(dataitems[0]);

                var left = nodes.SingleOrDefault(i => i.Label == label);
                if (left == null)
                {
                    left = new Node(label);
                    nodes.Add(left);
                }

                foreach (var item in dataitems.Skip(1))
                {
                    var itemLabel = Int32.Parse(item);
                    var right = nodes.SingleOrDefault(i => i.Label == itemLabel);
                    if (right == null)
                    {
                        right = new Node(itemLabel);
                        nodes.Add(right);
                    }

                    var existingEdge =
                        edges.SingleOrDefault(e => (e.Left.Label == left.Label && e.Right.Label == right.Label)
                                                   || (e.Left.Label == right.Label && e.Right.Label == left.Label));

                    if (existingEdge == null)
                    {
                        var edge = new Edge(++edgeId, left, right);
                        edges.Add(edge);
                    }
                }
            }

            return new Graph(nodes, edges);
        }
        public void Execute(Node startingNode)
        {
            startingNode.Visited = true;
            _visited.Enqueue(startingNode);

            while (_visited.Any())
            {
                var node = _visited.Dequeue();

                var neighbors = _graph.SelectNotVisitedNodes(node);

                foreach (var neighbor in neighbors)
                {
                    neighbor.Visited = true;
                    neighbor.Distance = node.Distance + 1;
                    _visited.Enqueue(neighbor);
                }
            }
        }
        public IGraph Build()
        {
            var lines = File.ReadAllLines(_file);
            var countData = lines[0].Split(_seperator, StringSplitOptions.RemoveEmptyEntries);
            var nodeCount = Int32.Parse(countData[0]);
            var edgeCount = nodeCount*nodeCount;

            var nodes = new Node[nodeCount + 1]; //+1 since nodes are 1 based
            var edges = new List<Edge>(edgeCount);
            var edgeId = 0;

            foreach (var line in lines.Skip(1))
            {
                var dataitems = line.Split(_seperator, StringSplitOptions.RemoveEmptyEntries);

                var leftNodeId = Int32.Parse(dataitems[0]);
                var rightNodeId = Int32.Parse(dataitems[1]);
                var weight = Int32.Parse(dataitems[2]);

                var leftNode = nodes[leftNodeId];
                if (leftNode == null)
                {
                    leftNode = new Node(leftNodeId);
                    nodes[leftNodeId] = leftNode;
                }

                var rightNode = nodes[rightNodeId];
                if (rightNode == null)
                {
                    rightNode = new Node(rightNodeId);
                    nodes[rightNodeId] = rightNode;
                }

                var edge = new Edge(++edgeId, leftNode, rightNode, EdgeDirection.None, weight);
                edges.Add(edge);
            }

            var finalNodes = nodes.Skip(1).ToList();
            var finalEdges = edges.OrderBy(e => e.Weight).ToList();
            return new Graph(finalNodes, finalEdges);
        }
        public IGraph Build()
        {
            var lines = File.ReadAllLines(_file).Skip(1).ToArray(); //skip comment line
            var countData = lines[0].Split(_seperator, StringSplitOptions.RemoveEmptyEntries);
            var verticeCount = Int32.Parse(countData[0]);
            var edgeCount = Int32.Parse(countData[1]);

            var nodes = new Node[verticeCount + 1]; //since nodes are 1 based
            var edges = new List<Edge>(edgeCount);
            var edgeId = 0;

            foreach (var line in lines.Skip(1)) //skip size line
            {
                var data = line.Split(_seperator, StringSplitOptions.RemoveEmptyEntries);
                var tailLabel = Int32.Parse(data[0]);
                var headLabel = Int32.Parse(data[1]);
                var edgeCost = Int32.Parse(data[2]);

                var tail = nodes[tailLabel];
                if (tail == null)
                {
                    tail = new Node(tailLabel);
                    nodes[tailLabel] = tail;
                }

                var head = nodes[headLabel];
                if (head == null)
                {
                    head = new Node(headLabel);
                    nodes[headLabel] = head;
                }

                var edge = new Edge(++edgeId, tail, head, EdgeDirection.LeftToRight, edgeCost);
                edges.Add(edge);

                nodes[headLabel].IncomingEdges.Add(edge);
            }

            var finalNodes = nodes.Skip(1).ToList();
            return new Graph(finalNodes, edges);
        }
        public int Calculate()
        {
            var lines = File.ReadAllLines(_file).Skip(1).ToArray(); //skip comment line
            var countData = lines[0].Split(_seperator, StringSplitOptions.RemoveEmptyEntries);
            var nodeCount = Int32.Parse(countData[0]);
            var edgeBitSize = Int32.Parse(countData[1]);

            var possibleNumberOfNodes = (int) Math.Pow(2, edgeBitSize);
            var possibleNodes = new Node[possibleNumberOfNodes];
            var possibleClusters = new HashSet<int>[possibleNumberOfNodes];

            var nodes = new List<Node>(nodeCount);

            foreach (var line in lines.Skip(1)) //skip size line
            {
                var bits = line.Split(_seperator, StringSplitOptions.RemoveEmptyEntries).Reverse()
                    .Select(l => l == "1").ToArray();

                var bitArray = new BitArray(bits);
                var number = new int[1];
                bitArray.CopyTo(number, 0);
                var nodeNumber = number[0];
                var node = new Node(nodeNumber);

                //ignore duplicates
                if (possibleNodes[nodeNumber] == null)
                {
                    nodes.Add(node);
                    possibleNodes[nodeNumber] = node;
                }
            }

            var possibleNeighbors = GetPossibleNeighbors(edgeBitSize);
            var clusterCount = 0;

            foreach (var node in nodes)
            {
                //i am at least my own neighbor
                if (node.ClusterId == 0)
                {
                    node.ClusterId = node.Label;
                    possibleClusters[node.ClusterId] = new HashSet<int>(new[] { node.Label });
                    ++clusterCount;
                }

                foreach (var possibleNeighbor in possibleNeighbors)
                {
                    var possibleNeighborIndex = node.Label ^ possibleNeighbor;
                    var otherNode = possibleNodes[possibleNeighborIndex];
                    if (otherNode == null) continue;

                    //add neighbor to my cluster
                    if (otherNode.ClusterId == 0)
                    {
                        otherNode.ClusterId = node.ClusterId;
                        possibleClusters[node.ClusterId].Add(otherNode.Label);
                    }
                    //merging clusters
                    else if (node.ClusterId != otherNode.ClusterId)
                    {
                        var newLeader = possibleClusters[otherNode.ClusterId].Count > possibleClusters[node.ClusterId].Count
                            ? otherNode.ClusterId
                            : node.ClusterId;

                        var oldLeader = newLeader == otherNode.ClusterId ? node.ClusterId : otherNode.ClusterId;

                        //get those who have old leader, and set those to new leader
                        possibleClusters[oldLeader]
                            .ToList()
                            .ForEach(n =>
                            {
                                possibleNodes[n].ClusterId = newLeader;
                                possibleClusters[newLeader].Add(n);
                            });

                        possibleClusters[oldLeader] = null;

                        --clusterCount;
                    }
                }
            }

            return clusterCount;
        }
        public IGraph Build()
        {
            var lines = File.ReadAllLines(_file).Skip(1).ToArray(); //skip comment line
            var countData = lines[0].Split(_seperator, StringSplitOptions.RemoveEmptyEntries);
            var size = Int32.Parse(countData[0]);

            var nodes = new Node[2*size + 1]; //+1 for 1-based index, *2 for neg values

            var edges = new List<Edge>(2*size);
            var edgeId = 0;

            foreach (var line in lines.Skip(1)) //skip size line
            {
                var data = line.Split(_seperator, StringSplitOptions.RemoveEmptyEntries);
                var leftNodeId = Int32.Parse(data[0]);
                var rightNodeId = Int32.Parse(data[1]);

                var leftNodeId1 = -leftNodeId;
                var rightNodeId1 = rightNodeId;

                var leftNodeId2 = -rightNodeId;
                var rightNodeId2 = leftNodeId;

                ////////////////////////////////////
                //left node 1
                var leftIndex1 = (leftNodeId1 < 0) ? (size - leftNodeId1) : leftNodeId1;

                var leftNode1 = nodes[leftIndex1];
                if (leftNode1 == null)
                {
                    leftNode1 = new Node(leftNodeId1);
                    nodes[leftIndex1] = leftNode1;
                }

                ////////////////////////////////////
                //left node 2
                var leftIndex2 = (leftNodeId2 < 0) ? (size - leftNodeId2) : leftNodeId2;

                var leftNode2 = nodes[leftIndex2];
                if (leftNode2 == null)
                {
                    leftNode2 = new Node(leftNodeId2);
                    nodes[leftIndex2] = leftNode2;
                }

                ////////////////////////////////////
                //right node 1
                var rightIndex1 = (rightNodeId1 < 0) ? (size - rightNodeId1) : rightNodeId1;

                var rightNode1 = nodes[rightIndex1];
                if (rightNode1 == null)
                {
                    rightNode1 = new Node(rightNodeId1);
                    nodes[rightIndex1] = rightNode1;
                }

                ////////////////////////////////////
                //right node 1
                var rightIndex2 = (rightNodeId2 < 0) ? (size - rightNodeId2) : rightNodeId2;

                var rightNode2 = nodes[rightIndex2];
                if (rightNode2 == null)
                {
                    rightNode2 = new Node(rightNodeId2);
                    nodes[rightIndex2] = rightNode2;
                }

                leftNode1.Outgoing.Add(rightNode1);
                rightNode1.Incoming.Add(leftNode1);
                leftNode2.Outgoing.Add(rightNode2);
                rightNode2.Incoming.Add(leftNode2);

                var edge1 = new Edge(++edgeId, leftNode1, rightNode1, EdgeDirection.LeftToRight);
                var edge2 = new Edge(++edgeId, leftNode2, rightNode2, EdgeDirection.LeftToRight);
                edges.Add(edge1);
                edges.Add(edge2);
            }

            var finalNodes = nodes.Where(n => n != null).ToList();
            return new Graph2(finalNodes, edges);
        }