#include<bits/stdc++.h>
#define range(i,a,b) for(int i = (a); i < (b); i++)
#define rep(i,b) for(int i = 0; i < (b); i++)
#define all(a) (a).begin(), (a).end()
#define show(x)  cerr << #x << " = " << (x) << endl;
//const int INF = 1e8;
using namespace std;

class EulerGraph{
	private:
		bool directed;
		bool isList;
		vector<vector<int>> g;
		int degreeCheck(int a){
			if(a == 0) return EULER_GRAPH;
			else if(a == 2) return SEMI_EULER_GRAPH;
			else return 0;
		}
		int degreeCheck(vector<vector<int>> d){
			int s = 0, t = 0, p = 0;
			for(auto i : d){
				if(i[0] == i[1] + 1) s++;
				else if(i[0] == i[1]) t++;
				else p++;
			}
			if(s == 0 && t == 0) return EULER_GRAPH;
			else if(s == 1 && t == 1) return SEMI_EULER_GRAPH;
			else return 0;
		}
		int checkEulerDirectedList(){
			vector<vector<int>> degree(g.size(), vector<int>(2,0)); //0:out, 1:in
			rep(i,g.size()){
				degree[i][0] = g[i].size();
				for(auto j : g[i]){
					degree[j][1]++;
				}
			}
			return degreeCheck(degree);
		}
		int checkEulerIndirectedList(){
			int a = 0;
			rep(i,g.size()){
				if(g[i].size() % 2) a++;
			}
			return degreeCheck(a);
		}
		int checkEulerDirectedMat(){
			vector<vector<int>> degree(g.size(), vector<int>(2,0)); //0:out, 1:in
			rep(i,g.size()){
				rep(j,g[i].size()){
					if(g[i][j] > 0){
						degree[i][0]++;
						degree[j][1]++;
					}
				}
			}
			return degreeCheck(degree);
		}
		int checkEulerIndirectedMat(){
			int a = 0;
			rep(i,g.size()){
				int degree = 0;
				rep(j,g[i].size()){
					if(g[i][j] > 0) degree++;
				}
				if(degree % 2) a++;
			}
			return degreeCheck(a);
		}
		//g?????£??\?????????
		//g?????´?£???????
		//?§?????????£??\?????????????????????????????????
		vector<int> ListEulerianTrail(const int s, const bool directed) {
			function<void (int, vector<int> &)> dfs = [&](int u, vector<int> &trail) {
				while (not g[u].empty()) {
					int v = g[u].back();
					g[u].pop_back();
					if (not directed) {
						for (int i = 0; i < g[v].size(); i ++) {
							if (g[v][i] == u) {
								g[v].erase(g[v].begin() + i);
								break;
							}
						}
					}
					dfs(v, trail);
				}
				trail.emplace_back(u);
			};
			vector<int> trail;
			dfs(s, trail);
			reverse(trail.begin(), trail.end());
			return trail;
		}
		//g?????£??\??????
		//g?????´?£???????
		vector<int> MatEulerianTrail(const int s, const bool directed) {
			function<void (int, vector<int> &)> dfs = [&](int u, vector<int> &trail) {
				for (int v = 0; v < g.size(); v ++) if (g[u][v] > 0) {
					g[u][v]--;
					if (not directed) g[v][u]--;
					dfs(v, trail);
				}
				trail.push_back(u);
			};
			vector<int> trail;
			dfs(s, trail);
			reverse(trail.begin(), trail.end());
			return trail;
		}
	public:
		EulerGraph(vector<vector<int>> g, bool directed, bool isList){
			this->g = g;
			this->directed = directed;
			this->isList = isList;
		}

		static const int EULER_GRAPH = 1;
		static const int SEMI_EULER_GRAPH = 2;
		int isEulerGraph(){
			if(isList){
				if(directed) return checkEulerDirectedList();
				else return checkEulerIndirectedList();
			}else{
				if(directed) return checkEulerDirectedMat();
				else return checkEulerIndirectedMat();
			}
			return -1;
		}
		vector<int> getEulerianTrail(const int s){
			if(isList) return ListEulerianTrail(s,directed);
			else return MatEulerianTrail(s, directed);
		}
		bool test(){
			if(g[0].size() % 2 == 0) return false;
			if(g[0].size() % 2 == 0) return false;
			range(i,2,100){
				if(g[i].size() % 2 == 1) return false;
			}
			return true;
		}
};

int main(){
	while(true){
		vector<vector<int>> g(100);
		int a, b;
		bool loop = false;
		while(cin >> a >> b, a||b){
			a--; b--;
			g[a].emplace_back(b);
			g[b].emplace_back(a);
			loop = true;
		}
		if(not loop) break;

		EulerGraph euler(g, 0, 1);
		cout << (euler.test() ? "OK" : "NG") << endl;
	}
}

Measured memory_bytes: 3176