import std.stdio;
import std.ascii;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;
import std.c.string;
import std.random;
import std.regex;
import std.typecons;

/* 重みつきUnionFind木 */
class UnionFindW {
    struct Pair {
        int index, value;
    }
    int[] parent;
    int[] value;
    static const int INF = 1<<28;
    this(int N) {
        parent = new int[N + 1]; parent[] = -1;
        value = new int[N + 1];  value[] = 0;
    }
    /* 
     * root :: インデックス -> (ルートのインデックス, ルートとの距離)
     */
    Pair root(int x) {
        if (parent[x] == -1) return Pair(x, 0);
        int p = parent[x];
        int v = value[x];
        auto proot = root(p);
        parent[x] = proot.index;
        value[x] = v + proot.value;
        return Pair(parent[x], value[x]);
    }
    /* 
     * query :: (インデックスx, インデックスy) -> yとxの差
     */
    int query(int x, int y) {
        auto xroot = root(x),
             yroot = root(y);
        if (xroot.index != yroot.index) return INF;
        return yroot.value - xroot.value;
    }
    /*
     * merge :: (インデックスx, インデックスy, yとxの差w) -> ()
     *
     * xとyがすでに親子関係を持っていて,その差がwでなければ異常終了
     */
    void merge(int x, int y, int w) {
        auto xroot = root(x),
             yroot = root(y);
        if (xroot.index == yroot.index) {
            assert(query(x, y) == w);
            return;
        }
        int px = xroot.index, py = yroot.index;
        int dx = xroot.value, dy = yroot.value;
        /* value[y] - value[x] = w
         * value[x] - value[px] = dx
         * value[y] - value[py] = dy
         * value[py] - value[px] = (value[y] - dy) - (value[x] - dx)
         *                       = (value[y] - value[x]) - (dy - dx)
         *                       = w - dy + dx
         */
        parent[py] = px;
        value[py] = w - dy + dx;
    }
}

void main() {
    int N, M;
    UnionFindW uf;

    bool solve() {
        scanf("%d %d\n", &N, &M);
        if (N == 0 && M == 0) return false;
        uf = new UnionFindW(N);
        foreach (i; 0 .. M) {
            string s; readf("%s ", &s);
            int a, b, w;
            if (s == "!") {
                scanf("%d %d %d\n", &a, &b, &w);
                a--; b--;
                uf.merge(a, b, w);
            } else {
                scanf("%d %d\n", &a, &b);
                a--; b--;
                auto ans = uf.query(a, b);
                if (ans == UnionFindW.INF) {
                    writeln("UNKNOWN");
                } else {
                    writeln(ans);
                }
            }
        }
        return true;
    }
    
    while (solve) {}
}