public class Solution {
    private TVal Get<TKey, TVal>(Dictionary<TKey, TVal> d, TKey key, Func<TKey, TVal> constructor) {
        if (!d.ContainsKey(key)) {
            d[key] = constructor(key);
        }
        return d[key];
    }

    private Dictionary<int, List<int>> GetGraph(int[][] edges) {
        var g = new Dictionary<int, List<int>>();

        foreach (int[] edge in edges) {
            var (u, v) = (edge[0], edge[1]);
            Get(g, u, _ => new List<int>()).Add(v);
            Get(g, v, _ => new List<int>()).Add(u);
        }

        return g;
    }

    private record BFSEntry(int Node, int Index);

    public int SecondMinimum(int n, int[][] edges, int time, int change) {
        var graph = GetGraph(edges);

        var distances = new int[n + 1, 2];
        for (var i = 1; i <= n; ++i) {
            distances[i, 0] = distances[i, 1] = -1;
        }

        var q = new Queue<BFSEntry>();
        q.Enqueue(new BFSEntry(1, 0));
        distances[1, 0] = 0;

        while (q.TryDequeue(out var entry)) {
            var spentTime = distances[entry.Node, entry.Index];
            if ((spentTime / change) % 2 == 1) {
                spentTime = time + change * (spentTime / change + 1);
            } else {
                spentTime += time;
            }

            if (!graph.ContainsKey(entry.Node)) {
                continue;
            }

            foreach (var node in graph[entry.Node]) {
                if (distances[node, 0] == -1) {
                    distances[node, 0] = spentTime;
                    q.Enqueue(new BFSEntry(node, 0));
                } else if (distances[node, 1] == -1 && distances[node, 0] != spentTime) {
                    if (node == n) {
                        return spentTime;
                    }

                    distances[node, 1] = spentTime;
                    q.Enqueue(new BFSEntry(node, 1));
                }
            }
        }

        return 0;
    }
}