//O(V+E) void RunDFSForSCC(int node) { _nodeDict[node] = new NodeDiscAndLow { DiscoveryTime = _time, EarliestAccessibleNode = _time }; _time++; _inStack.Add(node); _myStack.Push(node); foreach (var nbor in _adj[node]) { if (_nodeDict.ContainsKey(nbor)) //Already processed { if (_inStack.Contains(nbor)) //BackEdge, ignore cross edges { //For BE u->v, EAN (Earliest Accessible Node) is Min(u.EAN,v.DiscoveryTime) _nodeDict[node].EarliestAccessibleNode = Math.Min(_nodeDict[node].EarliestAccessibleNode, _nodeDict[nbor].DiscoveryTime); } } else { RunDFSForSCC(nbor); //Update EarliestAccessibleNode _nodeDict[node].EarliestAccessibleNode = Math.Min(_nodeDict[node].EarliestAccessibleNode, _nodeDict[nbor].EarliestAccessibleNode); } } //When exiting check if this is the start of a strongly connected component if (_nodeDict[node].EarliestAccessibleNode == _nodeDict[node].DiscoveryTime) //Is a strongly connected component { var component = new List <int>(); PopFromStack(_nodeDict[node].EarliestAccessibleNode, component); _components.Add(component); } }
//O(V+E) void RunDFSForBridges(int node, int parent) { _nodeDict[node] = new NodeDiscAndLow { DiscoveryTime = _time, EarliestAccessibleNode = _time }; _time++; if (parent != -1) { _parents.Add(node, parent); } var childrenCount = 0; //Track children count foreach (var nbor in _adj[node]) { childrenCount++; if (nbor == parent) { continue; } if (_nodeDict.ContainsKey(nbor)) { _nodeDict[node].EarliestAccessibleNode = Math.Min(_nodeDict[node].EarliestAccessibleNode, _nodeDict[nbor].DiscoveryTime); } else { RunDFSForBridges(nbor, node); _nodeDict[node].EarliestAccessibleNode = Math.Min(_nodeDict[node].EarliestAccessibleNode, _nodeDict[nbor].EarliestAccessibleNode); if (_nodeDict[nbor].EarliestAccessibleNode > _nodeDict[node].DiscoveryTime)//Bridge { _bridges.Add(new SharedClasses.Edge { FromNode = node, ToNode = nbor }); } if (parent == -1 && childrenCount > 1) //If this is the root, and it has 2 or more children, it must be an articulation point. { _artPoints.Add(node); } else if (parent != -1 && _nodeDict[nbor].EarliestAccessibleNode >= _nodeDict[node].DiscoveryTime)//IF not root, this is an Articulation point { _artPoints.Add(node); } } } }