private void StrongConnect(
            ref int index,
            Stack <TarjanNode <TTrigger> > S,
            Dictionary <UpdateNode <TTrigger>, TarjanNode <TTrigger> > tarjanInfo,
            List <IEnumerable <UpdateNode <TTrigger> > > SCC,
            TarjanNode <TTrigger> v)
        {
            v.Index   = index;
            v.LowLink = index;
            index++;
            S.Push(v);
            v.OnStack = true;

            foreach (var node in GetTriggeredNodes(v.Node.OutgoingTriggers))
            {
                if (!tarjanInfo.TryGetValue(node, out var w))
                {
                    w = new TarjanNode <TTrigger>(node);
                    tarjanInfo.Add(node, w);
                    StrongConnect(ref index, S, tarjanInfo, SCC, w);
                    v.LowLink = Math.Min(w.LowLink, v.LowLink);
                }
                else if (w.OnStack)
                {
                    v.LowLink = Math.Min(v.LowLink, w.Index);
                }
            }

            if (v.LowLink == v.Index)
            {
                var cycle = new List <UpdateNode <TTrigger> >();
                while (S.Peek() != v)
                {
                    var w = S.Pop();
                    w.OnStack = false;
                    cycle.Add(w.Node);
                }
                cycle.Add(S.Pop().Node);
                if (cycle.Count > 1)
                {
                    SCC.Add(cycle);
                }
            }
        }
        private IEnumerable <IEnumerable <UpdateNode <TTrigger> > > FindStronglyConnectedComponents(IEnumerable <TTrigger> triggers)
        {
            var startNodes = GetTriggeredNodes(triggers);

            var SCC        = new List <IEnumerable <UpdateNode <TTrigger> > >();
            var S          = new Stack <TarjanNode <TTrigger> >();
            var tarjanInfo = new Dictionary <UpdateNode <TTrigger>, TarjanNode <TTrigger> >();
            var index      = 0;

            foreach (var node in startNodes)
            {
                if (!tarjanInfo.TryGetValue(node, out var v))
                {
                    v = new TarjanNode <TTrigger>(node);
                    tarjanInfo.Add(node, v);
                    StrongConnect(ref index, S, tarjanInfo, SCC, v);
                }
            }

            return(SCC);
        }