Problem:
こぶたぬきつねこ
A子さんの家に親戚のB男君がやってきました。彼は3歳で歌が大好きです。彼は幼稚園でならった「こぶたぬきつねこ」(山本直純作詞・作曲)という歌を一生懸命に歌っています。この歌では、4つのことば「こぶた」  「たぬき」 「きつね」「ねこ」が順にしりとりになっていて、さらに最後の音と最初の音が同じになっています。B男君は、A子さんに、同じようなしりとりが、B男君が言った単語から作れるか教えて欲しいと言われました。
そこで、A子さんを助けるために、与えられた単語から、その単語をすべて使って、順にしりとりをつくり、その上で、 第1 の単語の最初の文字と最終の単語の最後の文字が同じであるようにできるか否かを判定するプログラムを作成しましょう。
n
個の単語を入力とし、それらの単語の組からしりとりを作成できるか否かを判定し、可能な場合はOK と、不可能な場合は NG と出力するプログラムを作成してください。
Input
複数のデータセットの並びが入力として与えられます。入力の終わりはゼロひとつの行で示されます。
各データセットは以下の形式で与えられます。
n
word
1
word
2
:
word
n
1 行目に単語の個数
n
(2 ≤
n
≤ 10000) が与えられます。続く
n
行に
n
個の単語
word
i
(32 文字以下の半角英小文字だけからなる文字列) が与えられます。
データセットの数は 50 を超えません。
Output
入力データセットごとに、判定結果を１行に出力します。
Sample Input
5
apple
yellow
georgia
king
email
7
apple
yellow
georgia
king
email
wink
lucky
0
Output for the Sample Input
NG
OK

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

int dfs(int v, vector<vector<int>> const& es, vector<bool>& visited) {
    int res = 1;
    visited[v] = true;
    for(int i=0; i<es[v].size(); ++i) {
        if(!visited[es[v][i]]) {
            res += dfs(es[v][i], es, visited);
        }
    }
    return res;
}

int main() {
    int n;
    while(cin >> n, n) {
        vector<int> first(26), last(26);
        vector<vector<int>> edge(26);
        vector<bool> visited(26);
        set<char> appear;
        for(int i=0; i<n; ++i) {
            string s;
            cin >> s;
            first[s[0] - 'a']++;
            last[s.back() - 'a']++;
            edge[s[0]-'a'].push_back(s.back() - 'a');
            appear.insert(s[0]-'a');
            appear.insert(s.back()-'a');
        }
        bool ok = dfs(*appear.begin(), edge, visited) == appear.size();
        for(int i=0; i<26; ++i) {
            ok &= first[i] == last[i];
        }
        if(ok) {
            cout << "OK" << endl;
        } else {
            cout << "NG" << endl;
        }
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3540
final_rank: 12

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll=long long;
ll n;
string s;
int main(void){
    while(cin>>n,n){
        ll a[26][26]={},b[26]={},c[26][26],d1=0,d2=0,e1=0,e2=0;
        for(ll i=0;i<n;i++){
            cin>>s;
            a[s[0]-'a'][s[s.size()-1]-'a']++;
            b[s[0]-'a']++;
            b[s[s.size()-1]-'a']++;
        }
        for(ll i=0;i<26;i++){
            for(ll j=0;j<26;j++){
                e1+=a[i][j];
                e2+=a[j][i];
            }
            if(e1!=e2){
                d1++;
            }
            e1=e2=0;
        }
        if(!d1){
            for(ll i=0;i<26;i++){
                for(ll j=0;j<26;j++){
                    c[i][j]=(a[i][j] ? 1 : 1e9);
                }
            }
        }
        if(!d1){
            for(ll k=0;k<26;k++){
                for(ll i=0;i<26;i++){
                    for(ll j=0;j<26;j++){
                        c[i][j]=min(c[i][j],c[i][k]+c[k][j]);
                    }
                }
            }
        }
        if(!d1){
            for(ll i=0;i<26;i++){
                for(ll j=0;j<26;j++){
                    if(i!=j && b[i] && b[j] && c[i][j]==1e9){
                        d2++;
                    }
                }
            }
        }
        cout<<((d1 || d2) ? "NG\n" : "OK\n");
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3124
final_rank: 2

code_snippet: // common part begin
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cfenv>
#include <cfloat>
#include <chrono>
#include <cinttypes>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdarg>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <fstream>
#include <functional>
#include <initializer_list>
#include <iomanip>
#include <ios>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <streambuf>
#include <string>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;
#define INF (1ll) << 60
#define rep(i, n) for (long long i = 0; i < n; i++)
#define all(v) v.begin(), v.end()
typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
void chmax(ll &a, ll b)
{
  if (a < b)
    a = b;
}
void chmin(ll &a, ll b)
{
  if (a > b)
  {
    a = b;
  }
}
// common part end
#define hi_ cout << "hi" << endl;
#define yes cout << "yes" << endl
#define no cout << "no" << endl
#define Yes cout << "Yes" << endl
#define No cout << "No" << endl
#define llV(name, size)                   \
  std::vector<long long> name(size);      \
  for (unsigned int i = 0; i < size; i++) \
  cin >> name[i]
#define die(x)       \
  cout << x << endl; \
  return 0;
class Print
{
public:
  Print() {}
};

void operator<<(Print p, vector<ll> v)
{
  for (auto i : v)
    cout << i << " ";
  cout << endl;
}

void operator<<(Print p, vector<vector<ll>> v)
{
  for (auto i : v)
  {
    for (auto j : i)
    {
      cout << j << " ";
    }
    cout << endl;
  }
}

void operator<<(Print p, ull x)
{
  cout << x << endl;
}
void operator<<(Print p, vector<ull> v)
{
  for (auto i : v)
    cout << i << " ";
  cout << endl;
}

void operator<<(Print p, vector<vector<ull>> v)
{
  for (auto i : v)
  {
    for (auto j : i)
    {
      cout << j << " ";
    }
    cout << endl;
  }
}

void operator<<(Print p, ll x)
{
  cout << x << endl;
}

void operator<<(Print p, string s)
{
  cout << s << endl;
}
void operator<<(Print p, vector<string> s)
{
  for (auto i : s)
    cout << i << endl;
}

void operator<<(Print p, vector<pair<pair<ll, ll>, ll>> v)
{
  for (auto i : v)
  {
    cout << i.first.first << " " << i.first.second << " " << i.second << endl;
  }
}
void operator<<(Print p, vector<pair<ll, pair<ll, ll>>> v)
{
  for (auto i : v)
  {
    cout << i.first << " " << i.second.first << " " << i.second.second << endl;
  }
}
void operator<<(Print p, pair<ll, ll> v)
{
  cout << v.first << " " << v.second << endl;
}

Print print;

// //0-1 dfs
// class Maze
// {
// public:
//   vector<vector<ll>> G;
//   ll H, W;
//   function<vector<pair<pair<ll, ll>, ll>>(pair<ll, ll>)> destination;
//   Maze(vector<vector<ll>> G_, function<vector<pair<pair<ll, ll>, ll>>( pair<ll, ll>)> destination_) : G(G_), H(G_.size()), W(G_.at(0).size()), destination(destination_)
//   {
//   }

//   void solve(pair<ll, ll> S, pair<ll, ll> T)
//   {
//     deque<pair<pair<ll, ll>, ll>> q;
//     q.push({S, 0});
//     while (!q.empty())
//     {
//       pair<ll, ll> now = q.front().first;
//       ll c = q.front().second;
//       q.pop();
//       auto next = destination(now);
//       for (auto n : next)
//       {

//       }
//     }
//   }
// };
// class Maze01
// {
// public:
//   vector<vector<ll>> G;
//   function<vector<pair<pair<ll, ll>, ll>>(pair<ll, ll>)> destination;
//   ll H, W;
//   // 1 is # 0 is .
//   Maze01(vector<vector<ll>> G_, function<vector<pair<pair<ll, ll>, ll>>(pair<ll, ll>)> destination_) : G(G_), H(G.size()), W(G.at(0).size()), destination(destination_)
//   {
//   }

//   vector<vector<ll>> solve(pair<ll, ll> S)
//   {
//     if (G[S.first][S.second] == 1)
//       return vector<vector<ll>>(H, vector<ll>(W, INF));
//     deque<pair<pair<ll, ll>, ll>> q;
//     q.push_back({S, 0});
//     vector<vector<ll>> dis(H, vector<ll>(W, INF));
//     dis[S.first][S.second] = 0;
//     while (!q.empty())
//     {
//       auto now = q.front();
//       q.pop_front();
//       auto next = destination(now.first);
//       for (auto n : next)
//       {
//         ll h = n.first.first;
//         ll w = n.first.second;
//         ll c = n.second;
//         if (h < 0 || H <= h || w < 0 || w >= W)
//         {
//           continue;
//         }
//         if (dis[h][w] != INF)
//           continue;
//         if (G[h][w] == 1)
//           continue;
//         dis[h][w] = dis[now.first.first][now.first.second] + c;
//         if (c)
//         {
//           q.push_back({{h, w}, c});
//         }
//         else
//         {
//           q.push_front({{h, w}, c});
//         }
//       }
//     }
//     return dis;
//   }
// };

// class Maze
// {
// public:
//   vector<vector<ll>> G;
//   function<vector<pair<ll, ll>>(pair<ll, ll>)> destination;
//   ll H, W;
//   // 1 is # 0 is .
//   Maze(vector<vector<ll>> G_, function<vector<pair<ll, ll>>(pair<ll, ll>)> destination_) : G(G_), H(G.size()), W(G.at(0).size()), destination(destination_)
//   {
//   }

//   vector<vector<ll>> solve(pair<ll, ll> S)
//   {
//     if (G[S.first][S.second] == 1)
//       return vector<vector<ll>>(H, vector<ll>(W, INF));
//     queue<pair<ll, ll>> q;
//     q.push(S);
//     vector<vector<ll>> dis(H, vector<ll>(W, INF));
//     dis[S.first][S.second] = 0;
//     while (!q.empty())
//     {
//       auto now = q.front();
//       q.pop();
//       auto next = destination(now);
//       for (auto n : next)
//       {
//         if (n.first < 0 || H <= n.first || n.second < 0 || n.second >= W)
//         {
//           continue;
//         }
//         if (dis[n.first][n.second] != INF)
//           continue;
//         if (G[n.first][n.second] == 1)
//           continue;
//         dis[n.first][n.second] = dis[now.first][now.second] + 1;
//         q.push({n.first, n.second});
//       }
//     }
//     return dis;
//   }
// };
template <typename T>
map<T, T> prime_factor(T n)
{
  map<T, T> ret;
  for (T i = 2; i * i <= n; i++)
  {
    T tmp = 0;
    while (n % i == 0)
    {
      tmp++;
      n /= i;
    }
    ret[i] = tmp;
  }
  if (n != 1)
    ret[n] = 1;
  return ret;
}
const int N_MAX = 2000000;
ll spf[N_MAX]; // smallest prime factors
void prepare_factorize()
{
  rep(i, N_MAX) spf[i] = i;
  for (int p = 2; p * p <= N_MAX; p++)
  {
    for (int i = p; i < N_MAX; i += p)
    {
      if (spf[i] == i)
        spf[i] = p;
    }
  }
}

// 素因数分解
// その素因数が何個あるかのmapを返す
map<ll, ll> factorize_fast(ll n)
{
  if (spf[1] == 0)
  {
    // p("please initialize");
    exit(0);
  }
  map<ll, ll> mp;
  while (n != 1)
  {
    ll p = spf[n];
    mp[p]++;
    n /= p;
  }
  return mp;
}

// 約数の種類数
// 6 => 1, 2, 3, 6なので4
ll yaku(ll n)
{
  auto mp = factorize_fast(n);
  ll ret = 1;
  for (auto pa : mp)
  {
    ret *= (pa.second + 1);
  }
  return ret;
}

class SCC
{
public:
  vector<ll> used;
  vector<ll> rused;
  vector<vector<ll>> G;
  vector<vector<ll>> rG;
  vector<ll> vs;
  vector<ll> cmp;
  vector<vector<ll>> groups; // groupごとの要素を記録。
  ll N;
  SCC(ll N_, vector<vector<ll>> G_) : N(N_), used(N_), rused(N_), G(G_), rG(N_), cmp(N_, -1), groups(N_)
  {
    rep(i, N)
    {
      for (auto e : G[i])
      {
        rG[e].push_back(i);
      }
    }
  }
  void dfs(ll now)
  {
    used[now] = 1;
    for (auto e : G[now])
    {
      if (used[e])
        continue;
      dfs(e);
    }
    vs.push_back(now);
  }
  void rdfs(ll now, ll k)
  {
    rused[now] = 1;
    cmp[now] = k;
    groups[k].push_back(now);
    for (auto e : rG[now])
    {
      if (rused[e])
        continue;
      rdfs(e, k);
    }
  }
  ll scc()
  {
    ll k = 0;
    rep(i, N)
    {
      if (!used[i])
        dfs(i);
    }
    for (ll i = vs.size() - 1; i >= 0; i--)
    {
      if (!rused[vs[i]])
      {
        rdfs(vs[i], k);
        k++;
      }
    }
    return k;
  }
};

template <int MOD>
struct ModInt
{
  static const int Mod = MOD;
  unsigned x;
  ModInt() : x(0) {}
  ModInt(signed sig) { x = sig < 0 ? sig % MOD + MOD : sig % MOD; }
  ModInt(signed long long sig) { x = sig < 0 ? sig % MOD + MOD : sig % MOD; }
  int get() const { return (int)x; }
  ModInt &operator+=(ModInt that)
  {
    if ((x += that.x) >= MOD)
      x -= MOD;
    return *this;
  }
  ModInt &operator-=(ModInt that)
  {
    if ((x += MOD - that.x) >= MOD)
      x -= MOD;
    return *this;
  }
  ModInt &operator*=(ModInt that)
  {
    x = (unsigned long long)x * that.x % MOD;
    return *this;
  }
  ModInt &operator/=(ModInt that) { return *this *= that.inverse(); }
  ModInt operator+(ModInt that) const { return ModInt(*this) += that; }
  ModInt operator-(ModInt that) const { return ModInt(*this) -= that; }
  ModInt operator*(ModInt that) const { return ModInt(*this) *= that; }
  ModInt operator/(ModInt that) const { return ModInt(*this) /= that; }
  ModInt inverse() const
  {
    long long a = x, b = MOD, u = 1, v = 0;
    while (b)
    {
      long long t = a / b;
      a -= t * b;
      std::swap(a, b);
      u -= t * v;
      std::swap(u, v);
    }
    return ModInt(u);
  }
  bool operator==(ModInt that) const { return x == that.x; }
  bool operator!=(ModInt that) const { return x != that.x; }
  ModInt operator-() const
  {
    ModInt t;
    t.x = x == 0 ? 0 : Mod - x;
    return t;
  }
};

template <int MOD>
ostream &operator<<(ostream &st, const ModInt<MOD> a)
{
  st << a.get();
  return st;
};

template <int MOD>
ModInt<MOD> operator^(ModInt<MOD> a, unsigned long long k)
{
  ModInt<MOD> r = 1;
  while (k)
  {
    if (k & 1)
      r *= a;
    a *= a;
    k >>= 1;
  }
  return r;
}

typedef ModInt<1000000000 + 7> mint1_7;
typedef ModInt<998244353> mint9_3;
class CC
{
public:
  vector<ll> used;
  vector<vector<ll>> G;
  vector<vector<ll>> groups; // groupごとの要素を記録。
  ll N;
  CC(ll N_, vector<vector<ll>> G_) : N(N_), used(N_), G(G_), groups(N_)
  {
  }
  void dfs(ll now, ll group)
  {
    groups[group].push_back(now);
    used[now] = 1;
    for (auto e : G[now])
    {
      if (used[e])
        continue;
      dfs(e, group);
    }
  }

  ll cc()
  {
    ll k = 0;
    rep(i, N)
    {
      if (!used[i])
      {
        dfs(i, k);
        k++;
      }
    }
    return k;
  }
};
int main()
{
  while (true)
  {
    ll n;
    cin >> n;
    vector<ll> out_deg(26),in_deg(26);
    vector<vector<ll>> G(26);
    if (n == 0)
      break;
    rep(i, n)
    {
      string S;
      cin >> S;
      ll u = S[0] - 97;
      ll t = S[S.length() - 1] - 97;
      out_deg[u]++;
      in_deg[t]++;
      G[u].push_back(t);
      G[t].push_back(u);
    }
    CC S(G.size(), G);
    ll c = 0;
    rep(i, G.size()) if (G[i].size() == 0) c++;
    ll k = S.cc();
    if (k - c != 1)
    {
      cout << "NG" << endl;
      continue;
    }
    // print<<in_deg;print<<out_deg;
    bool flag = true;
    rep(i, 26) if ((in_deg[i]!=out_deg[i])) flag = false;
    if (flag)
    {
      cout << "OK" << endl;
    }
    else
    {
      cout << "NG" << endl;
    }

  }
}

// memo
// igaito maniau
accuracy: 1
time_ms: 10
memory_kb: 3540
final_rank: 12

code_snippet: #include<bits/stdc++.h>
using namespace std;

struct UnionFind{
  vector<int> par,siz;
  UnionFind(int n):par(n,-1),siz(n,1){}
  int root(int x){
    if(par[x] == -1) return x;
    else return par[x] = root(par[x]);
  }
  bool issame(int x,int y){
    if(root(x) == root(y)) return true;
    else return false;
  }
  bool unite(int x,int y){
    x = root(x);
    y = root(y);
    if(x == y) return false;
    if(siz[x] < siz[y]) swap(x,y);
    par[y] = x;
    siz[x] += siz[y];
    return true;
  }
  int size(int x){
    return siz[root(x)];
  }
};

int main(){
  for(;;){
    int N;
    cin >> N;
    if(N == 0) break;
    UnionFind uf(26);
    vector<bool> appear(26,false);
    vector<vector<int>> C(26,vector<int>(2,0));
    for(int i=0;i<N;i++){
      string word;
      cin >> word;
      char a = word[0];
      char b = word.back();
      uf.unite(a-'a',b-'a');
      appear[a-'a'] = true;
      appear[b-'a'] = true;
      C[a-'a'][0]++;
      C[b-'a'][1]++;
    }
    bool allsame = true;
    for(int i=0;i<26;i++) if(C[i][0] != C[i][1]) allsame = false;
    vector<bool> seen(N,false);
    int cnt = 0;
    for(int i=0;i<26;i++){
      if(!appear[i]) continue;
      if(seen[uf.root(i)]) continue;
      seen[uf.root(i)] = true;
      cnt++;
    }
    if(allsame && cnt == 1) cout << "OK" << endl;
    else cout << "NG" << endl;
  }
}
accuracy: 1
time_ms: 10
memory_kb: 3464
final_rank: 9

code_snippet: #include<bits/stdc++.h>

using namespace std;
using ll = long long;
using pint = pair<int,int>;
void solve(int);

int main()
{
	while(true) {
		int N; cin >> N;
		if(N == 0) return 0;
		else solve(N);
	}
}

class UnionFind{
  private:
	vector<int> data;
  public:
	UnionFind(int n) : data(n,-1) {}
	int root(int i) { return data[i] < 0 ? i : data[i] = root(data[i]); }
	int size(int i) { return -data[root(i)]; }
	bool same(int x, int y) {return root(x) == root(y); }
	bool connected() {return size(0) == (int)data.size(); }

	bool unit(int i,int j){
		i = root(i);
		j = root(j);
		if(i != j){
			data[i] += data[j];
			data[j] = i;
		}
		return i != j;
	}
};

void solve(int N)
{
	int AL = 26;
	vector<int> in(AL), ot(AL);
	UnionFind uf(AL);
	char c;
	for(int i = 0; i < N; i++) {
		string s; cin >> s;
		ot[s[0] - 'a']++;
		in[s.back() - 'a']++;
		uf.unit(s[0] - 'a', s.back() - 'a');
		c = s[0] - 'a';
	}
	
	bool ok = true;
	for(int i = 0; i < AL; i++) if(ot[i] != in[i]) ok = false;
	for(int i = 0; i < AL; i++) if(uf.root(i) != uf.root(c) && uf.size(i) != 1)ok = false;
	cout << (ok ? "OK" : "NG") << endl;


}
accuracy: 1
time_ms: 10
memory_kb: 3488
final_rank: 11

code_snippet: #include<bits//stdc++.h>
using namespace std;
int n,in[26],out[26];
bool d[26][26],used[26];
void f(int u){
    if(used[u])return;
	used[u]=1;
	for(int i=0;i<26;i++){
		if(!d[u][i])continue;
		f(i);
	}
}
main(){
	while(cin>>n,n){
	    for(int i=0;i<26;i++){
	        in[i]=out[i]=0;used[i]=1;
	        for(int j=0;j<26;j++)d[i][j]=0;
	    }
	    int st;
	    for(int i=0;i<n;i++){
		    string s;cin>>s;
		    int a=s[0]-'a',b=s[s.size()-1]-'a';
		    if(i==0)st=a;
		    in[a]++;out[b]++;
		    d[a][b]=d[b][a]=1;used[a]=used[b]=0;
		}
		f(st);
		bool ok=1;
		for(int i=0;i<26;i++)ok&=in[i]==out[i]&&used[i];
		cout<<(ok?"OK":"NG")<<endl;
	}
}
accuracy: 1
time_ms: 20
memory_kb: 3136
final_rank: 16

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct UnionFind{
    vector<int> v;
    int cc;
    
    UnionFind(int n): v(n, -1), cc(n){}
    int root(int x){
        if(v[x] < 0) return x;
        return v[x] = root(v[x]);
    }
    bool is_same(int x, int y){
        return root(x) == root(y);
    }
    bool unite(int x, int y){
        x = root(x);
        y = root(y);
        if(x == y) return false;
        if(v[y] < v[x]) swap(x, y);
        v[x] += v[y];
        v[y] = x;
        cc--;
        return true;
    }
    int size(int x){
        return -v[root(x)];
    }
};

int main(){
    while(1){
        int n;
        cin >> n;
        if(n == 0) break;

        vector<int> d(26, 0);
        vector<bool> used(26, false);
        UnionFind uf(26);
        for(int i=0; i<n; i++){
            string s;
            cin >> s;
            int a = s[0]-'a';
            int b = s.back()-'a';
            d[a]++;
            d[b]--;
            uf.unite(a, b);
            used[a] = used[b] = true;
        }
        bool ok = true;
        for(int i=0; i<26; i++){
            if(d[i]!=0) ok = false;
        }
        int num = 0;
        for(int i=0; i<26; i++){
            if(used[i]) num++;
        }
        if(uf.cc > 26-num+1) ok = false;
        if(ok){
            cout << "OK" << endl;
        }else{
            cout << "NG" << endl;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3012
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<int, int>;

bool visited[26], g[26][26];
int in[26], out[26];

void dfs(int v) {
    visited[v] = true;
    for (int u = 0; u < 26; u++) {
        if (visited[u]) continue;
        if (!g[v][u]) continue;
        dfs(u);
    }
}

int main() {
    int n;
    while (cin >> n && n) {
        for (int i = 0; i < 26; i++) {
            visited[i] = false;
            in[i] = out[i] = 0;
            for (int j = 0; j < 26; j++) {
                g[i][j] = false;
            }
        }
        for (int i = 0; i < n; i++) {
            string s;
            cin >> s;
            in[s.back() - 'a']++;
            out[s.front() - 'a']++;
            g[s.front() - 'a'][s.back() - 'a'] = true;
        }
        for (int i = 0; i < 26; i++) {
            if (in[i] == 0 && out[i] == 0) continue;
            dfs(i);
            break;
        }
        bool flag = true;
        for (int i = 0; i < 26; i++) {
            if (in[i] == 0 && out[i] == 0) continue;
            if (!visited[i]) flag = false;
        }
        for (int i = 0; i < 26; i++) {
            if (in[i] != out[i]) flag = false;
        }
        if (flag) cout << "OK" << endl;
        else cout << "NG" << endl;
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3188
final_rank: 18

code_snippet: #include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
#define reps(i,b,n) for(int i = b ; i < (int)n ; ++i )
#define rep(i,n) reps(i,0,n)
bool flg[26];
int buff[26];
vector<int> vc[26];
void dfs(int c){
  flg[c] = false;
  rep(i,vc[c].size()) if(flg[vc[c][i]]) dfs(vc[c][i]);
}
int main(){
  int n;
  string str;
  while(cin >> n , n){
    bool ok = true;
    rep(i,26)vc[i].clear();
    fill_n(flg,26,false);
    fill_n(buff,26,0);
    int l,r;
    rep(i,n){
      cin >> str;
      l = str[0] - 'a' , r = str[str.size()-1] - 'a';
      vc[l].push_back(r);
      buff[l]++ , buff[r]--;
      flg[l] = flg[r] = true;
    }
    dfs(l);
    rep(i,26){
      if(flg[i]||buff[i]){
        ok = false;
        break;
      }
    }
    cout << (ok ? "OK" : "NG") << endl;
  }
}
accuracy: 1
time_ms: 10
memory_kb: 3228
final_rank: 6

code_snippet: #include <iostream>
#include <vector>
#define repeat(i,n) for (int i = 0; (i) < (n); ++(i))
using namespace std;
int main() {
    while (true) {
        int n; cin >> n;
        if (n == 0) break;
        bool g[26][26] = {};
        bool used[26] = {};
        int d[26] = {}; // relative degree
        repeat (i,n) {
            string s; cin >> s;
            int x = s.front() - 'a';
            int y = s.back()  - 'a';
            used[x] = true;
            used[y] = true;
            g[x][y] = true;
            d[x] += 1;
            d[y] -= 1;
        }
        repeat (k,26) { // warshall floyd
            repeat (i,26) {
                repeat (j,26) {
                    if (g[i][k] and g[k][j]) g[i][j] = true;
                }
            }
        }
        bool ans = true;
        repeat (i,26) {
            if (d[i] != 0) ans = false; // eulerlian cycle
        }
        repeat (i,26) if (used[i]) {
            repeat (j,26) if (used[j]) {
                if (not g[i][j]) {
                    ans = false; // not connected
                }
            }
        }
        cout << (ans ? "OK" : "NG") << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3084
final_rank: 15

code_snippet: #include<bits/stdc++.h>

using namespace std;

int WordsDegree[26];
bool Route[26][26], UsedHead[26], UsedTail[26];


bool judgeSide() {
	for (int i = 0; i < 26;++i) {
		if (WordsDegree[i] != 0) {
			return false;
		}
	}
	return true;
}

bool judgeCircle() {
	for (int k = 0; k < 26; ++k) {
		for (int i = 0; i < 26; ++i) {
			for (int j = 0; j < 26; ++j) {
				if (Route[i][k] && Route[k][j]) {
					Route[i][j] = true;
				}
			}
		}
	}

	for (int i = 0; i < 26; ++i) {
		if (!UsedHead[i]) {
			continue;
		}
		for (int j = 0; j < 26; ++j) {
			if (!UsedTail[j]) {
				continue;
			}
			if (!Route[i][j]) {
				return false;
			}
		}
	}
	return true;
}

int main() {
	int n,head,tail;
	string str;

	while (cin >> n, n) {
		memset(WordsDegree, 0, sizeof(WordsDegree));
		memset(Route, false, sizeof(Route));
		memset(UsedHead, false, sizeof(UsedHead));
		memset(UsedTail, false, sizeof(UsedTail));
		for (int i = 0; i < n; ++i) {
			cin >> str;
			//cout << "head:" << str.front() << "   tail:" << str.back() << endl;
			//head = str.front() - 'a';
			//tail = str.back() - 'a';
			head = str[0] - 'a';
			tail = str[str.size() - 1] - 'a';
			++WordsDegree[head];
			--WordsDegree[tail];
			Route[head][tail] = true;
			UsedHead[head] = true;
			UsedTail[tail] = true;
		}
		if (judgeSide() && judgeCircle()) {
			cout << "OK" << endl;
		}
		else {
			cout << "NG" << endl;
		}
	}

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3156
final_rank: 5

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

class UnionFind {
    int n;
    vector<int> uni;
    int forest_size;
public:
    explicit UnionFind(int n) : n(n), uni(static_cast<u32>(n), -1), forest_size(n) {};

    int root(int a){
        if (uni[a] < 0) return a;
        else return (uni[a] = root(uni[a]));
    }

    bool unite(int a, int b) {
        a = root(a);
        b = root(b);
        if(a == b) return false;
        if(uni[a] > uni[b]) swap(a, b);
        uni[a] += uni[b];
        uni[b] = a;
        forest_size--;
        return true;
    }
    int size(){ return forest_size; }
    int size(int i){ return -uni[root(i)]; }
    bool same(int a, int b) { return root(a) == root(b); }
};

int main() {
    int n;
    while(cin >> n, n){
        array<int, 256> cnt{};
        int a = 0;
        fill(cnt.begin(), cnt.end(), -1);
        vector<int> in(26), out(26);
        UnionFind uf(26);
        for (int i = 0; i < n; ++i) {
            string s;
            cin >> s;
            if(!~cnt[s.front()]) cnt[s.front()] = a++;
            if(!~cnt[s.back()]) cnt[s.back()] = a++;
            uf.unite(cnt[s.front()], cnt[s.back()]);
            in[cnt[s.front()]]++;
            out[cnt[s.back()]]++;
        }
        int ok = 1;
        for (int i = 0; i < a; ++i) {
            if(in[i] != out[i]) ok = 0;
        }
        if(uf.size(0) == a && ok) puts("OK");
        else puts("NG");
    }
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 2976
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;

bool circuit(vvi &to) {
    int in[26] = {}, ou[26] = {};
    for (int i=0; i<(int)to.size(); ++i) {
        for (int j: to[i]) {
            in[i] ++;
            ou[j] ++;
        }
    }
    for (int i=0; i<26; ++i) {
        if (in[i] != ou[i]) return false;
    }
    return true;
}

bool connected(vvi &to) {
    int s = 0;
    while (to[s].empty()) s ++;
    bool used[26] = {};
    stack<int> st;
    st.push(s);
    while ( ! st.empty()) {
        int t = st.top();
        st.pop();
        if (used[t]) continue;
        used[t] = true;
        for (int u: to[t]) st.push(u);
    }
    for (int i=0; i<(int)to.size(); ++i) {
        for (int j: to[i]) {
            if ( ! used[i] || ! used[j]) return false;
        }
    }
    return true;
}

int main() {
    int N;
    while (cin >> N, N) {
        vvi to(26);
        string s;
        for (int i=0; i<N; ++i) {
            cin >> s;
            to[s[0]-'a'].push_back(s.back()-'a');
        }
        if (circuit(to) && connected(to)) {
            cout << "OK\n";
        } else {
            cout << "NG\n";
        }
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3020
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

vector<int> G[26];
bool flag[26];
bool visited[26];
int degree[26];

void dfs(int v) {
    visited[v] = true;
    
    for (int i=0; i<G[v].size(); i++) {
        if (!visited[G[v][i]]) {
            dfs(G[v][i]);
        }
    }
}

int main() {
    while (true) {
        int n; cin >> n;
        
        if (n==0) {
            break;
        }
        
        for (int i=0; i<26; i++) {
            G[i].clear();
        }
        
        for (int i=0; i<26; i++) {
            flag[i] = false;
            visited[i] = false;
            degree[i] = 0;
        }
        
        int s, t;
        
        for (int i=0; i<n; i++) {
            string w; cin >> w;
            s = w[0]-'a';
            t = w[w.size()-1]-'a';
            G[s].push_back(t);
            flag[s] = true;
            flag[t] = true;
            degree[s]++;
            degree[t]--;
        }
        
        dfs(s);
        
        bool judge = true;
        
        for (int i=0; i<26; i++) {
            if (flag[i] && !visited[i]) {
                judge &= false;
            }
            
            if (degree[i]!=0) {
                judge &= false;
            }
        }
        
        if (judge) {
            cout << "OK" << endl;
        }
        else {
            cout << "NG" << endl;
        }
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3216
final_rank: 19

code_snippet: #pragma GCC optimize ("O3")

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <queue>
#include <set>
#include <algorithm>
#include <numeric>
#include <list>
using namespace std;

using QWORD  = uint64_t;
using SQWORD = int64_t;
using DWORD  = uint32_t;
using SDWORD = int32_t;
using WORD   = uint16_t;
using SWORD  = int16_t;
using BYTE   = uint8_t;
using SBYTE  = int8_t;
using DOUBLE = double;
using FLOAT  = float;

#define MIN_SDWORD (-2147483648)
#define MAX_SDWORD (2147483647)
#define MIN_SBYTE (-128)
#define MAX_SBYTE (127)

#define MIN_SQWORD (0x8000000000000000)
#define MAX_SQWORD (0x7FFFFFFFFFFFFFFF)

#define MAX_QWORD  (0xFFFFFFFFFFFFFFFF)
#define MAX_DWORD  (0xFFFFFFFF)
#define MAX_WORD   (0xFFFF)
#define MAX_BYTE   (0xFF)

#define MAX_DOUBLE      (1.0e+308)
#define DOUBLE_EPS      (1.0e-12)
#define MIN_DOUBLE_N    (-1.0e+308)

#define ArrayLength(a)  (sizeof(a) / sizeof(a[0]))

static inline DOUBLE MAX(DOUBLE a, DOUBLE b) { return a > b ? a : b; }
static inline QWORD MAX(QWORD a, QWORD b) { return a > b ? a : b; }
static inline DWORD MAX(DWORD a, DWORD b) { return a > b ? a : b; }
static inline SDWORD MAX(SDWORD a, SDWORD b) { return a > b ? a : b; }
static inline DOUBLE MIN(DOUBLE a, DOUBLE b) { return a < b ? a : b; }
static inline QWORD MIN(QWORD a, QWORD b) { return a < b ? a : b; }
static inline DWORD MIN(DWORD a, DWORD b) { return a < b ? a : b; }
static inline SDWORD MIN(SDWORD a, SDWORD b) { return a < b ? a : b; }

#define BYTE_BITS   (8)
#define WORD_BITS   (16)
#define DWORD_BITS  (32)
#define QWORD_BITS  (64)

static inline void inputStringSpSeparated(char *pcStr)
{
    char *pcCur = pcStr;
    for (;;) {
        char c = getchar();
        if (('\n' == c) || (EOF == c) || (' ' == c)) {
            break;
        }
        *pcCur = c;
        pcCur++;
    }
    *pcCur = '\0';
}

static inline void inputString(char *pcStr)
{
    char *pcCur = pcStr;
    for (;;) {
        char c = getchar();
        if (('\n' == c) || (EOF == c)) {
            break;
        }
        *pcCur = c;
        pcCur++;
    }
    *pcCur = '\0';
}


static inline SQWORD inputSQWORD(void)
{
    SQWORD sqNumber = 0;
    SQWORD sqMultiplier = 1;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                sqMultiplier = -1;
            }
        }
        if (('0' <= c) && (c <= '9')) {
            sqNumber *= 10LL;
            sqNumber += (SQWORD)(c - '0');
            bRead = true;
        } else {
            if (bRead) {
                return sqNumber * sqMultiplier;
            }
        }
    }
}


static inline SDWORD inputSDWORD(void)
{
    SDWORD lNumber = 0;
    SDWORD lMultiplier = 1;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                lMultiplier = -1;
            }
        }
        if (('0' <= c) && (c <= '9')) {
            lNumber *= 10;
            lNumber += (c - '0');
            bRead = true;
        } else {
            if (bRead) {
                return lNumber * lMultiplier;
            }
        }
    }
}

static inline DOUBLE inputFP(void)
{
    DOUBLE dInt = 0.0;
    DOUBLE dFrac = 0.0;
    DOUBLE dMultiplier = 1.0;
    DWORD dwFpCnt = 0;
    DOUBLE *pdCur = &dInt;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                dMultiplier = -1;
            }
        }
        if ('.' == c) {
            pdCur = &dFrac;
        } else if (('0' <= c) && (c <= '9')) {
            (*pdCur) *= 10;
            (*pdCur) += (DOUBLE)(c - '0');
            bRead = true;
            if (pdCur == &dFrac) {
                dwFpCnt++;
            }
        } else {
            if (bRead) {
                return dMultiplier * (dInt + dFrac / (pow((DOUBLE)10.0 , (DOUBLE)dwFpCnt)));
            }
        }
    }
}

/*----------------------------------------------*/
/**
 *  mod による操作ライブラリ
 */
#define ANS_MOD (1000000007)

class MODINT {
    static SQWORD MOD;
    SQWORD m_x;

public:
    MODINT(SQWORD val) {
        m_x = (val % MOD + MOD) % MOD;
    };
    MODINT() {
        m_x = 0;
    }
    static void Init(SQWORD sqMod) {
        MOD = sqMod;
    }

	MODINT& operator+= (const MODINT a)
    {
        m_x = (m_x + a.m_x) % MOD; 
        return *this;
    };
	MODINT& operator-= (const MODINT a)
    { 
        m_x = (m_x - a.m_x + MOD) % MOD; 
        return *this;
    };
	MODINT& operator*= (const MODINT a)
    {
        m_x = (m_x * a.m_x) % MOD;
        return *this;
    };
    MODINT pow(SQWORD t) const {
        if (!t) return 1;
        MODINT a = pow(t>>1);
        a *= a;
        if (t&1) a *= *this;
        return a;
    }
	MODINT operator+ (const MODINT a) const {
		MODINT res(*this);
		return (res += a);
	}
	MODINT operator- (const MODINT a) const {
		MODINT res(*this);
		return (res -= a);
	}
	MODINT operator* (const MODINT a) const {
		MODINT res(*this);
		return (res *= a);
	}
	MODINT operator/ (const MODINT a) const {
		MODINT res(*this);
		return (res /= a);
	}

    /* 逆元 */
    MODINT inv() const {
        return pow(MOD-2);
    }

    /* 除算 */
    MODINT& operator/=(const MODINT a) {
        return (*this) *= a.inv();
    } 

    /* 整数版 */
	MODINT& operator+= (const SQWORD a) {*this += MODINT(a); return *this;};
	MODINT& operator-= (const SQWORD a) {*this -= MODINT(a); return *this;};
	MODINT& operator*= (const SQWORD a) {*this *= MODINT(a); return *this;};
	MODINT& operator/= (const SQWORD a) {*this /= MODINT(a); return *this;};

    SQWORD getVal() { return m_x; };
};
SQWORD MODINT::MOD = ANS_MOD;


typedef struct {
    vector<DWORD>   vdwPar;
    vector<DWORD>   vdwRank;
    vector<DWORD>   vdwCnt;
    DWORD   dwSize;

    void initUnionFind(
        DWORD dwSize)
    {
        dwSize = dwSize;
        vdwPar.resize(dwSize);
        vdwRank.resize(dwSize);
        vdwCnt.resize(dwSize);
    
        for (DWORD dwIdx = 0; dwIdx < dwSize; dwIdx++) {
            vdwPar[dwIdx]  = dwIdx;
            vdwRank[dwIdx] = 0;
            vdwCnt[dwIdx]  = 1;
        }
    }

    DWORD ufGetCnt(DWORD sqIdx) {
        return vdwCnt[ufGetParent(sqIdx)];
    }


    DWORD ufGetParent(DWORD dwIdx) const
    {
        return vdwPar[dwIdx];
    }

    DWORD ufGetRank(DWORD dwIdx) const
    {
        return vdwRank[dwIdx];
    }

    void ufSetParent(DWORD dwIdx, DWORD dwParent)
    {
        vdwPar[dwIdx] = dwParent; 
        if (ufGetRank(dwIdx) == ufGetRank(dwParent)) {
            (vdwRank[dwParent])++;
        }
    }

    DWORD ufGetRoot(DWORD dwIdx) const
    {
        if (ufGetParent(dwIdx) == dwIdx) {
            return dwIdx;
        } else {
            DWORD dwParent = ufGetParent(dwIdx);
            DWORD dwRoot = ufGetRoot(dwParent);
            return dwRoot;
        }
    }

    bool ufUnite(DWORD dwX, DWORD dwY)
    {
        DWORD dwRootX = ufGetRoot(dwX);
        DWORD dwRootY = ufGetRoot(dwY);

        if (dwRootX == dwRootY) {
            return false;
        }

        if (ufGetRank(dwRootX) < ufGetRank(dwRootY)) {
            ufSetParent(dwRootX, dwRootY);
            (vdwCnt[dwRootY]) += (vdwCnt[dwRootX]);
        } else {
            ufSetParent(dwRootY, dwRootX);
            (vdwCnt[dwRootX]) += (vdwCnt[dwRootY]);
        }

        return true;
    }

    bool ufIsSame(DWORD dwX, DWORD dwY) const
    {
        return (ufGetRoot(dwX)  == ufGetRoot(dwY));
    }
} ST_UNION_FIND;

/*----------------------------------------------*/
#define MAX_ALPHABETS   (26)

bool solve(void)
{
    SQWORD sqN = inputSQWORD();
    ST_UNION_FIND   uf;

    uf.initUnionFind(MAX_ALPHABETS);
    if (0 == sqN) {
        return false;
    }

    vector<SQWORD> vecsqIn(MAX_ALPHABETS, 0);
    vector<SQWORD> vecsqOut(MAX_ALPHABETS, 0);
   
    SQWORD sqBeginIdx = 0;
    for (SQWORD sqIdx = 0; sqIdx < sqN; sqIdx++) {
        string strS;
        cin >> strS;

        SQWORD sqFront = strS.front() - 'a';
        SQWORD sqTail = strS.back() - 'a';

        vecsqIn[sqTail]++;
        vecsqOut[sqFront]++;

        uf.ufUnite(sqFront, sqTail);
    }

    SQWORD sqParent = -1;
    for (SQWORD sqAlph = 0; sqAlph < MAX_ALPHABETS; sqAlph++) {
        if ((0 < vecsqOut[sqAlph]) || (0 < vecsqIn[sqAlph])) {
            if (-1 == sqParent) {
                sqParent = uf.ufGetRoot(sqAlph);
            } else {
                if (sqParent != uf.ufGetRoot(sqAlph)) {
                    printf("NG\n");
                    return true;
                }
            }
        }
    }

    for (SQWORD sqAlph = 0; sqAlph < MAX_ALPHABETS; sqAlph++) {
        if (vecsqOut[sqAlph] != vecsqIn[sqAlph]) {
            printf("NG\n");
            return true;
        }
    }
    printf("OK\n");
    return true;
}


int main(void)
{
    while(1) {
        bool bRet = solve();
        if (!bRet) {
            break;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3080
final_rank: 12

code_snippet: //#include "pch.h"
//#include "stdafx.h"
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <math.h>
#include <string>
#include <cstring>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>

using namespace std;

typedef long long int ll;
#define BIG_NUM 2000000000
using namespace std;

struct Info{

	Info(){
		left = right = 'X';
		index = 0;
	}

	Info(char arg_left,char arg_right,int arg_index){
		left = arg_left;
		right = arg_right;
		index = arg_index;
	}
	char left,right;
	int index;
};

bool check[10000];
vector<Info> V[26];

void dfs(char left){
	for(int i = 0; i < V[left - 'a'].size(); i++){
		if(check[V[left - 'a'][i].index] == false){
			check[V[left - 'a'][i].index] = true;
			dfs(V[left - 'a'][i].right);
		}
	}
}

int execOne(){

	int N,num_left[26],num_right[26];

	bool FLG;

	char last,final_start;
	string buf;

	while(true){
		cin >> N;
		if(N == 0)break;

		FLG = true;

		for(int i = 0; i < 26; i++){
			V[i].clear();
			num_left[i] = 0;
			num_right[i] = 0;
		}
		for(int i = 0; i < N; i++)check[i] = false;

		for(int i = 0; i < N; i++){
			cin >> buf;
			num_left[buf[0] - 'a']++;
			for(int k = 0; buf[k] != '\0'; k++)last = buf[k];
			num_right[last - 'a']++;
			V[buf[0]-'a'].push_back(Info(buf[0],last,i));
			final_start = buf[0];
		}

		for(int i = 0; i < 26; i++){
			if(num_left[i] != num_right[i]){
				printf("NG\n");
				FLG = false;
				break;
			}
		}

		if(!FLG)continue;

		check[V[final_start - 'a'][0].index] = true;
		dfs(V[final_start - 'a'][0].right);

		for(int i = 0; i < N; i++){
			if(check[i] == false){
				printf("NG\n");
				FLG = false;
				break;
			}
		}

		if(!FLG)continue;

		printf("OK\n");

	}

	return 0;
}

#if 0
/*-----------------------------------------------------------------------------
　ライブラリ
 -------------------------------------------------------------------------------*/
#if 0
// 3次元
vector<vector<vector<SDWORD>>> XXX(AAA, vector<vector<SDWORD>>(BBBB, vector<SDWORD>(CCC, -1)));
#endif

#if 0
// 降順ソート
sort(getValue.rbegin(), getValue.rend());
#endif

#if 0
// 2分探索
auto position = lower_bound(getValue.begin(), getValue.end(), 0);	// 0以上の要素位置を探す
int idx_lower = distance(getValue.begin(), position);				// 0以上の要素インデックス
int eraseNum = MIN(idx_lower, delCnt);								// 要素位置が個数になる
if (0 < eraseNum) {
	getValue.erase(getValue.begin(), getValue.begin() + eraseNum);
}
#endif

/*-----------------------------------------------------------------------------
　定義
 -------------------------------------------------------------------------------*/
#define REP(i, n) for (int (i) = 0 ; (i) < (int)(n) ; ++(i))
#define REPN(i, m, n) for (int (i) = m ; (i) < (int)(n) ; ++(i))
#define REP_REV(i, n) for (int (i) = (int)(n) - 1 ; (i) >= 0 ; --(i))
#define REPN_REV(i, m, n) for (int (i) = (int)(n) - 1 ; (i) >= m ; --(i))

#define INF				2e9
#define MOD				(1000 * 1000 * 1000 + 7)
#define MIN(a, b)		((a) < (b) ? a : b)
#define MAX(a, b)		((a) > (b) ? a : b)
#define CeilN(x, n)		(((((DWORD)(x))+((n)-1))/n)*n)	/* Nの倍数に切り上げ */
#define FloorN(x, n)	((x)-(x)%(n))					/* Nの倍数に切り下げ */
#define IsOdd(x)		(((x)&0x01UL) == 0x01UL)			
#define IsEven(x)		(!IsOdd((x)))						

#define ArrayLength(x)	( sizeof( x ) / sizeof( x[ 0 ] ) )
#define	ArrayEnd(a)		(&(a)[ArrayLength(a)])			
#define	ArrayLast(a)	(&(a)[ArrayLength(a) - 1])		
#define MAX_BYTE		(255)
#define MIN_BYTE		(0)
#define MAX_WORD		(65535)
#define MIN_WORD		(0)
#define MAX_SWORD		(32767)
#define MIN_SWORD		(-32768)
#define MAX_DWORD		(0xFFFFFFFF)
#define MIN_DWORD		(0)
#define	MAX_SDWORD		((SDWORD)0x7FFFFFFF)
#define	MIN_SDWORD		((SDWORD)0x80000000)
#define	MAX_QWORD		((QWORD)0xFFFFFFFFFFFFFFFF)
#define	MIN_QWORD		((QWORD)0x0000000000000000)
#define	MAX_SQWORD		((SQWORD)0x7FFFFFFFFFFFFFFF)
#define	MIN_SQWORD		((SQWORD)0x8000000000000000)

#define	BitSetV(Val,Bit)		((Val) |= (Bit))			
#define	BitClrV(Val,Bit)		((Val) &= (~(Bit)))			
#define	BitTstV(Val,Bit)		((Val) & (Bit))				
#define	BitInvV(Val,Bit)		((Val) ^= (Bit))			
#define	BitTstVVal(Val, Bit)	(BitTstV((Val), (Bit)) == (Bit))	

typedef short					SWORD;
typedef long					SDWORD;
typedef long long				SQWORD;
typedef unsigned short			WORD;
typedef unsigned long			DWORD;
typedef unsigned long long int	QWORD;
typedef pair<int, int> P;

/*-----------------------------------------------------------------------------
　パラメータ定義
 -------------------------------------------------------------------------------*/
#define N_MAX	(10)
#define K_MAX	(10)
#define M_MAX	(1000)
#define H_MAX	(1000)
#define W_MAX	(1000)
/*-----------------------------------------------------------------------------
　処理
 -------------------------------------------------------------------------------*/
///
struct wordInfo {
	wordInfo() {
		index = 0;
		to = 'Z';
	}

	wordInfo(int a, char b) {
		index = a;
		to = b;
	}
	int	index;
	int to;
};
vector<bool>		execResult;
vector<wordInfo>	wordList[26];

/// dfs
void dfs(int topWord)
{
	//	vector<wordInfo> &wordOne = wordList[topWord];

	for (size_t i = 0; i < wordList[topWord].size(); i++) {
		if (!execResult[wordList[topWord][i].index]) {
			execResult[wordList[topWord][i].index] = true;
			dfs(wordList[topWord][i].to);
		}
	}
}

/// 1塊判定
bool execOne(int n)
{
	int lastWord;
	int topNum[26];
	int endNum[26];

	// 初期化
	REP(i, 26) {
		wordList[i].clear();
		topNum[i] = 0;
		endNum[i] = 0;
	}
	execResult.resize(n, false);

	// 入力
	REP(i, n) {
		string strOne;
//		const char *pStrOne = strOne.c_str();
		cin >> strOne;
		int topWord = *strOne.begin() - 'a';
		int endWord = *(strOne.end() - 1) - 'a';
		topNum[topWord]++;
		endNum[endWord]++;
		wordList[topWord].push_back(wordInfo(i, endWord));
		lastWord = endWord;
	}

	// 先頭と末尾の数は一緒のはず
	REP(i, n) {
		if (topNum[i] != endNum[i]) {
			return false;
		}
	}

	// dfs
	execResult[n - 1] = true;
	dfs(lastWord);

	// 結果チェック
	REP(i, n) {
		if (!execResult[i]) {
			return false;
		}
	}
	return true;
}
#endif

/// メイン
int main()
{
	execOne();
	/*
	while (1) {
		int n;
		cin >> n;
		if (n == 0) {
			break;
		}
		if (execOne(n)) {
			cout << "OK" << endl;
		} else {
			cout << "NG" << endl;
		}
	}

	cout << endl;*/
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3140
final_rank: 4

code_snippet: //#include "pch.h"
//#include "stdafx.h"
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <math.h>
#include <string>
#include <cstring>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>

using namespace std;

typedef long long int ll;
#define BIG_NUM 2000000000
using namespace std;

struct Info{

	Info(){
		left = right = 'X';
		index = 0;
	}

	Info(char arg_left,char arg_right,int arg_index){
		left = arg_left;
		right = arg_right;
		index = arg_index;
	}
	char left,right;
	int index;
};

bool check[10000];
vector<Info> V[26];

void dfs(char left){
	for(int i = 0; i < V[left - 'a'].size(); i++){
		if(check[V[left - 'a'][i].index] == false){
			check[V[left - 'a'][i].index] = true;
			dfs(V[left - 'a'][i].right);
		}
	}
}

int main(){

	int N,num_left[26],num_right[26];

	bool FLG;

	char last,final_start;
	string buf;

	while(true){
		cin >> N;
		if(N == 0)break;

		FLG = true;

		for(int i = 0; i < 26; i++){
			V[i].clear();
			num_left[i] = 0;
			num_right[i] = 0;
		}
		for(int i = 0; i < N; i++)check[i] = false;

		for(int i = 0; i < N; i++){
			cin >> buf;
			num_left[buf[0] - 'a']++;
			for(int k = 0; buf[k] != '\0'; k++)last = buf[k];
			num_right[last - 'a']++;
			V[buf[0]-'a'].push_back(Info(buf[0],last,i));
			final_start = buf[0];
		}

		for(int i = 0; i < 26; i++){
			if(num_left[i] != num_right[i]){
				printf("NG\n");
				FLG = false;
				break;
			}
		}

		if(!FLG)continue;

		check[V[final_start - 'a'][0].index] = true;
		dfs(V[final_start - 'a'][0].right);

		for(int i = 0; i < N; i++){
			if(check[i] == false){
				printf("NG\n");
				FLG = false;
				break;
			}
		}

		if(!FLG)continue;

		printf("OK\n");

	}

	return 0;
}

#if 0
/*-----------------------------------------------------------------------------
　ライブラリ
 -------------------------------------------------------------------------------*/
#if 0
// 3次元
vector<vector<vector<SDWORD>>> XXX(AAA, vector<vector<SDWORD>>(BBBB, vector<SDWORD>(CCC, -1)));
#endif

#if 0
// 降順ソート
sort(getValue.rbegin(), getValue.rend());
#endif

#if 0
// 2分探索
auto position = lower_bound(getValue.begin(), getValue.end(), 0);	// 0以上の要素位置を探す
int idx_lower = distance(getValue.begin(), position);				// 0以上の要素インデックス
int eraseNum = MIN(idx_lower, delCnt);								// 要素位置が個数になる
if (0 < eraseNum) {
	getValue.erase(getValue.begin(), getValue.begin() + eraseNum);
}
#endif

/*-----------------------------------------------------------------------------
　定義
 -------------------------------------------------------------------------------*/
#define REP(i, n) for (int (i) = 0 ; (i) < (int)(n) ; ++(i))
#define REPN(i, m, n) for (int (i) = m ; (i) < (int)(n) ; ++(i))
#define REP_REV(i, n) for (int (i) = (int)(n) - 1 ; (i) >= 0 ; --(i))
#define REPN_REV(i, m, n) for (int (i) = (int)(n) - 1 ; (i) >= m ; --(i))

#define INF				2e9
#define MOD				(1000 * 1000 * 1000 + 7)
#define MIN(a, b)		((a) < (b) ? a : b)
#define MAX(a, b)		((a) > (b) ? a : b)
#define CeilN(x, n)		(((((DWORD)(x))+((n)-1))/n)*n)	/* Nの倍数に切り上げ */
#define FloorN(x, n)	((x)-(x)%(n))					/* Nの倍数に切り下げ */
#define IsOdd(x)		(((x)&0x01UL) == 0x01UL)			
#define IsEven(x)		(!IsOdd((x)))						

#define ArrayLength(x)	( sizeof( x ) / sizeof( x[ 0 ] ) )
#define	ArrayEnd(a)		(&(a)[ArrayLength(a)])			
#define	ArrayLast(a)	(&(a)[ArrayLength(a) - 1])		
#define MAX_BYTE		(255)
#define MIN_BYTE		(0)
#define MAX_WORD		(65535)
#define MIN_WORD		(0)
#define MAX_SWORD		(32767)
#define MIN_SWORD		(-32768)
#define MAX_DWORD		(0xFFFFFFFF)
#define MIN_DWORD		(0)
#define	MAX_SDWORD		((SDWORD)0x7FFFFFFF)
#define	MIN_SDWORD		((SDWORD)0x80000000)
#define	MAX_QWORD		((QWORD)0xFFFFFFFFFFFFFFFF)
#define	MIN_QWORD		((QWORD)0x0000000000000000)
#define	MAX_SQWORD		((SQWORD)0x7FFFFFFFFFFFFFFF)
#define	MIN_SQWORD		((SQWORD)0x8000000000000000)

#define	BitSetV(Val,Bit)		((Val) |= (Bit))			
#define	BitClrV(Val,Bit)		((Val) &= (~(Bit)))			
#define	BitTstV(Val,Bit)		((Val) & (Bit))				
#define	BitInvV(Val,Bit)		((Val) ^= (Bit))			
#define	BitTstVVal(Val, Bit)	(BitTstV((Val), (Bit)) == (Bit))	

typedef short					SWORD;
typedef long					SDWORD;
typedef long long				SQWORD;
typedef unsigned short			WORD;
typedef unsigned long			DWORD;
typedef unsigned long long int	QWORD;
typedef pair<int, int> P;

/*-----------------------------------------------------------------------------
　パラメータ定義
 -------------------------------------------------------------------------------*/
#define N_MAX	(10)
#define K_MAX	(10)
#define M_MAX	(1000)
#define H_MAX	(1000)
#define W_MAX	(1000)
/*-----------------------------------------------------------------------------
　処理
 -------------------------------------------------------------------------------*/
///
struct wordInfo {
	wordInfo() {
		index = 0;
		to = 'Z';
	}

	wordInfo(int a, char b) {
		index = a;
		to = b;
	}
	int	index;
	int to;
};
vector<bool>		execResult;
vector<wordInfo>	wordList[26];

/// dfs
void dfs(int topWord)
{
	//	vector<wordInfo> &wordOne = wordList[topWord];

	for (size_t i = 0; i < wordList[topWord].size(); i++) {
		if (!execResult[wordList[topWord][i].index]) {
			execResult[wordList[topWord][i].index] = true;
			dfs(wordList[topWord][i].to);
		}
	}
}

/// 1塊判定
bool execOne(int n)
{
	int lastWord;
	int topNum[26];
	int endNum[26];

	// 初期化
	REP(i, 26) {
		wordList[i].clear();
		topNum[i] = 0;
		endNum[i] = 0;
	}
	execResult.resize(n, false);

	// 入力
	REP(i, n) {
		string strOne;
//		const char *pStrOne = strOne.c_str();
		cin >> strOne;
		int topWord = *strOne.begin() - 'a';
		int endWord = *(strOne.end() - 1) - 'a';
		topNum[topWord]++;
		endNum[endWord]++;
		wordList[topWord].push_back(wordInfo(i, endWord));
		lastWord = endWord;
	}

	// 先頭と末尾の数は一緒のはず
	REP(i, n) {
		if (topNum[i] != endNum[i]) {
			return false;
		}
	}

	// dfs
	execResult[n - 1] = true;
	dfs(lastWord);

	// 結果チェック
	REP(i, n) {
		if (!execResult[i]) {
			return false;
		}
	}
	return true;
}

/// メイン
int main()
{
	while (1) {
		int n;
		cin >> n;
		if (n == 0) {
			break;
		}
		if (execOne(n)) {
			cout << "OK" << endl;
		} else {
			cout << "NG" << endl;
		}
	}

	cout << endl;
	return 0;
}


#endif
accuracy: 1
time_ms: 10
memory_kb: 3324
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
class UnionFind {
	vector<int> data;
	int root(int a) {
		return data[a] < 0 ? a : data[a] = root(data[a]);
	}
public:
	UnionFind(int n) : data(n, -1) {}
	bool Find(int a, int b) {
		return root(a) == root(b);
	}
	void Union(int a, int b) {
		a = root(a);
		b = root(b);
		if (a == b) return;
		if (data[a] < data[b]) {
			data[a] += data[b];
			data[b] = a;
		}
		else {
			data[b] += data[a];
			data[a] = b;
		}
	}
	int Size(int a) {
		return -data[root(a)];
	}
};


int main()
{
	int n;
	string word;
	while (cin >> n, n) {
		int cnt = 0;
		vector<int> s(26), e(26), used(26);
		UnionFind uf(26);
		while (n--) {
			cin >> word;
			int f = word.front() - 'a', b = word.back() - 'a';
			s[f]++;
			e[b]++;
			uf.Union(f, b);
			if (!used[f]) {
				cnt++;
				used[f] = 1;
			}
			if (!used[b]) {
				cnt++;
				used[b] = 1;
			}
		}
		bool res = true;
		for (int i = 0; i < 26; i++) {
			if (s[i] != e[i]) {
				res = false;
				break;
			}
		}
		cout << (res && uf.Size(word.front() - 'a') == cnt ? "OK" : "NG") << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3132
final_rank: 3

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<cctype>
#include<utility>
#include<string>
#include<cmath>
#include<cstring>
#include<queue>
#include<map>
#include<set>
#include<climits>

#define REP(i, n) for(int i = 0;i < n;i++)
#define REPR(i, n) for(int i = n;i >= 0;i--)
#define FOR(i, m, n) for(int i = m;i < n;i++)
#define FORR(i, m, n) for(int i = m;i >= n;i--)
#define SORT(v, n) sort(v, v+n);
#define VSORT(v) sort(v.begin(), v.end());
#define llong long long
#define pb(a) push_back(a)

using namespace std;

typedef long long int ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;


template<typename T>
vector<T> make_v(size_t a) { return vector<T>(a); }
template<typename T, typename... Ts>
auto make_v(size_t a, Ts... ts) {
	return vector<decltype(make_v<T>(ts...))>(a, make_v<T>(ts...));
}
template<typename T, typename V>
typename enable_if<is_class<T>::value == 0>::type
fill_v(T& t, const V& v) { t = v; }
template<typename T, typename V>
typename enable_if<is_class<T>::value != 0>::type
fill_v(T& t, const V& v) {
	for (auto& e : t) fill_v(e, v);
}


#define ARRAY_MAX 100005
const int INF = INT32_MAX / 3;
const ll MOD = 1e9 + 7;

int dx[4] = { 1,0,0,-1 };
int dy[4] = { 0,1,-1,0 };


/******************************************************************************************/


vector<int> G[30];
int st = 0;
int check[30];
int cnt[30];

void dfs(int now) {

	
	check[now] = 1;
	
	for (auto itr : G[now]) {

		if (check[itr] == 1)continue;
		dfs(itr);
	}
}



int main() {

	int n;
	while (cin >> n, n) {

		bool ok = true;
		for (int i = 0; i < n; i++)
		{
			string s;
			cin >> s;
			G[s[0] - 'a'].push_back(s.back() - 'a');
			cnt[s[0] - 'a']++;
			cnt[s.back() - 'a']--;
		}

		//入次数，出次数のチェック
		for (int i = 0; i < 26; i++)
		{
			if (cnt[i] != 0) {
				ok = false;
				break;
			}
		}
		
		for (int i = 0; i < 26; i++) {
			if (G[i].size() > 0) {
				dfs(i);
				break;
			}
		}
		

		for (int i = 0; i < 26; i++) {
			if (G[i].size() > 0 && !check[i]) {
				ok = false;
			}
		}

		if (ok) {
			cout << "OK" << endl;
		}
		else
		{
			cout << "NG" << endl;
		}

		
		for (int i = 0; i < 30; i++)
		{
			cnt[i] = 0;
			check[i] = 0;
			G[i].clear();
		}
	}

	


	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3180
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;

using i64 = int64_t;

using Graph = vector<vector<int>>;

class StronglyConnectedComponents {
  private:
    const Graph &graph;
    Graph g, rg;
    deque<int> order;
    deque<bool> used;
    vector<int> num_components;

    void dfs(int v) {
        used[v] = true;
        for (auto to : g[v]) {
            if (!used[to])
                dfs(to);
        }
        order.push_front(v);
    }

    void rdfs(int v, int k) {
        num_components[v] = k;
        for (auto to : rg[v]) {
            if (num_components[to] == -1)
                rdfs(to, k);
        }
    }

  public:
    StronglyConnectedComponents(Graph &graph)
        : graph(graph), g(graph.size()), rg(graph.size()), used(graph.size()),
          num_components(graph.size(), -1) {
        for (int i = 0; i < graph.size(); i++) {
            for (auto e : graph[i]) {
                g[i].push_back((int)e);
                rg[(int)e].push_back(i);
            }
        }
    }

    int operator[](int v) { return num_components[v]; }

    int decompose() {
        for (int v = 0; v < (int)g.size(); v++) {
            if (used[v])
                continue;
            dfs(v);
        }

        int k = 0;
        for (int v : order) {
            if (num_components[v] != -1)
                continue;
            rdfs(v, k);
            k++;
        }

        return k;
    }
};

int main(){
    int n;
    while(cin >> n, n > 0){
        vector<string> v;
        map<char, int> mp1, mp2;
        for(int i=0;i<n;++i){
            string s;
            cin >> s;
            v.push_back(s);
            mp1[s[0]]++;
            mp2[s.back()]++;
        }
        bool ok = true;
        for(char c='a';c<='z';++c){
            if(mp1[c] != mp2[c])ok = false;
        }
        if(!ok){
            cout << "NG" << endl;
            continue;
        }
        Graph graph(n, vector<int>());
        for(int i=0;i<n;++i){
            for(int j=0;j<n;++j){
                if(i==j)continue;
                if(v[i].back() == v[j][0]){
                    graph[i].push_back(j);
                }
            }
        }
        StronglyConnectedComponents scc(graph);
        scc.decompose();
        set<int> st;
        for(int i=0;i<n;++i){
            st.insert(scc[i]);
        }
        if(st.size() > 1)cout << "NG";
        else cout << "OK";
        cout << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3896
final_rank: 20