#include <bits/stdc++.h>
using namespace std;
#define int long long

#define ALL(c) c.begin(), c.end()
#define SZ(c) ((int)c.size())
#define REP(i, n) for (int i = 0, loop_num_##i = n; i < loop_num_##i; i++)


template<class Abel> struct UnionFind {
    vector<int> par;
    vector<int> rank;
    vector<Abel> diff_weight;

    UnionFind(int n = 1, Abel SUM_UNITY = 0) {
        init(n, SUM_UNITY);
    }

    void init(int n = 1, Abel SUM_UNITY = 0) {
        par.resize(n); rank.resize(n); diff_weight.resize(n);
        for (int i = 0; i < n; ++i) par[i] = i, rank[i] = 0, diff_weight[i] = SUM_UNITY;
    }

    int root(int x) {
        if (par[x] == x) {
            return x;
        }
        else {
            int r = root(par[x]);
            diff_weight[x] += diff_weight[par[x]];
            return par[x] = r;
        }
    }

    Abel weight(int x) {
        root(x);
        return diff_weight[x];
    }

    bool issame(int x, int y) {
        return root(x) == root(y);
    }

    bool merge(int x, int y, Abel w) {
        w += weight(x); w -= weight(y);
        x = root(x); y = root(y);
        if (x == y) return false;
        if (rank[x] < rank[y]) swap(x, y), w = -w;
        if (rank[x] == rank[y]) ++rank[x];
        par[y] = x;
        diff_weight[y] = w;
        return true;
    }

    Abel diff(int x, int y) {
        return weight(y) - weight(x);
    }
};
// quoted from: https://qiita.com/drken/items/cce6fc5c579051e64fab

signed main() {
	while (1) {
		int N, M;
		cin >> N >> M;
		if (N == 0 && M == 0) break;
		UnionFind<int> uf(N);
		REP(i, M) {
			char q;
			cin >> q;
			int a, b, w;
			if (q == '!') {
				cin >> a >> b >> w;
				a--, b--;
				uf.merge(a, b, w);
			} else {
				cin >> a >> b;
				a--, b--;
				if (uf.issame(a, b)) {
					cout << uf.diff(a, b) << endl;
				} else {
					cout << "UNKNOWN" << endl;
				}
			}
		}
	}
}

