Problem:
すごろくを作る

太郎君は、子供会の催しでみんなで遊べるようにすごろくを作りました。ゲームをおもしろくするために、「ふりだし」と「あがり」以外のすごろくのマスのいくつかに「６つ進む」、「５つ戻る」のように指示を書き込んでいきました。ルーレットを回して出た数だけ進み、止まったマスに指示が書き込んであれば、その指示に従って移動します。ただし、指示に従って進んだ先のマスの指示には従いません。

ルーレットは１からある数までの間の数を等確率で出すことができるものとします。また、「あがり」に達するより大きな数が出たときや、指示に従うと「あがり」より先に進んでしまうときは「あがり」に移動します。指示に従って戻るときに「ふりだし」より前に戻ってしまうときは「ふりだし」に戻ることにします。

ところが、ルーレットとマスの指示によっては「あがり」にたどりつけない場合が出てきてしまいます。たとえば、図のようなすごろくを作ったとしましょう。１と２しか出ないルーレットを使うと、１，２の順に出れば「あがり」に行けますが、はじめに２が出たらその後は何が出ても永久に「あがり」にはたどり着けません。太郎君は、そうとは知らずに調子に乗ってあちこちのマスに指示を書き込んでしまいました。

そこで、太郎君に代わって、ルーレットとマスの指示によっては、「あがり」にたどり着けない場合が生じるかどうか判定するプログラムを作成してください。

入力

入力は複数のデータセットからなる。入力の終わりはゼロ１つの行で示される。各データセットは以下の形式で与えられる。

max
n
d1
d2
.
.
.
dn

１行目にルーレットが出す数の最大値 max (2 ≤ max ≤ 250) が与えられ、２行目に「ふりだし」と「あがり」以外のマスの数 n (2 ≤ n ≤ 250) が与えられる。続く n 行に各マスの指示を表す数 di(-n ≤ di ≤ n) が与えられる。di がゼロのときは指示が書いていないことを、正の数のときは |di| 進む指示を、負の数のときは |di| 戻る指示を表す（ここで、|x| は x の絶対値を表す）。入力される値はすべて整数である。

データセットの数は 100 を超えない。

出力

各データセットごとに判定結果を１行に出力する。ルーレットとマスの指示によっては、「あがり」にたどり着けない場合が生じるときは「NG」、そうでなければ「OK」を出力する。

入力例

3
3
-2
1
0
2
4
2
0
-1
-2
2
2
-2
-2
0

出力例

OK
NG
NG

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace _0262
{
    class Program
    {
        static Dictionary<int, HashSet<int>> adj;
        static int max, n;
        static int[] direction;
        static bool[] sVisited, gVisited;

        static void Main(string[] args)
        {
            while (true)
            {
                max = RInt();
                if (max == 0) break;
                Init();
                GotoGoal();
                if (!adj.ContainsKey(n + 1))
                {
                    Console.WriteLine("NG");
                }
                else
                {
                    GotoStart();
                    bool flg = true;
                    for (int i = 1; i < sVisited.Length; i++)
                    {
                        if (sVisited[i] && !gVisited[i])
                        {
                            flg = false;
                            break;
                        }
                    }
                    Console.WriteLine(flg ? "OK" : "NG");
                }
            }
        }

        private static void Init()
        {
            n = RInt();
            direction = new int[n + 1];
            for (int i = 1; i <= n; i++) direction[i] = RInt();
            adj = new Dictionary<int, HashSet<int>>();
            sVisited = new bool[n + 2];
            gVisited = new bool[n + 2];
        }

        private static void GotoGoal()
        {
            Queue<int> q = new Queue<int>();
            q.Enqueue(0);

            while (q.Count > 0)
            {
                int cur = q.Dequeue();
                if (sVisited[cur]) continue;
                sVisited[cur] = true;

                for (int i = 1; i <= max; i++)
                {
                    if (cur + i >= n + 1)
                    {
                        if (!adj.ContainsKey(n + 1)) adj.Add(n + 1, new HashSet<int>());
                        adj[n + 1].Add(cur);
                    }
                    else
                    {
                        int next = cur + i + direction[cur + i];
                        if (next >= n + 1)
                        {
                            if (!adj.ContainsKey(n + 1)) adj.Add(n + 1, new HashSet<int>());
                            adj[n + 1].Add(cur);
                        }
                        else if (next < 0)
                        {
                            if (!adj.ContainsKey(0)) adj.Add(0, new HashSet<int>());
                            adj[0].Add(cur);
                        }
                        else
                        {
                            if (!adj.ContainsKey(next)) adj.Add(next, new HashSet<int>());
                            adj[next].Add(cur);
                            q.Enqueue(next);
                        }
                    }
                }
            }
        }

        private static void GotoStart()
        {
            Queue<int> q = new Queue<int>();
            q.Enqueue(n + 1);

            while (q.Count > 0)
            {
                int cur = q.Dequeue();
                if (gVisited[cur] || cur == 0) continue;
                gVisited[cur] = true;

                foreach (var next in adj[cur])
                {
                    q.Enqueue(next);
                }
            }
        }

        static string RSt() { return Console.ReadLine(); }
        static int RInt() { return int.Parse(Console.ReadLine().Trim()); }
        static long RLong() { return long.Parse(Console.ReadLine().Trim()); }
        static double RDouble() { return double.Parse(Console.ReadLine()); }
        static string[] RArSt(char sep = ' ') { return Console.ReadLine().Trim().Split(sep); }
        static int[] RArInt(char sep = ' ') { return Array.ConvertAll(Console.ReadLine().Trim().Split(sep), e => int.Parse(e)); }
        static long[] RArLong(char sep = ' ') { return Array.ConvertAll(Console.ReadLine().Trim().Split(sep), e => long.Parse(e)); }
        static double[] RArDouble(char sep = ' ') { return Array.ConvertAll(Console.ReadLine().Trim().Split(sep), e => double.Parse(e)); }
        static string WAr<T>(IEnumerable<T> array, string sep = " ") { return string.Join(sep, array.Select(x => x.ToString()).ToArray()); }
    }
}