import std.algorithm;
import std.array;
import std.ascii;
import std.container;
import std.conv;
import std.math;
import std.numeric;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void log(A...)(A arg) {
    stderr.writeln(arg);
}
int size(T)(in T s) {
    return cast(int)s.length;
}

/* ??\??????????????????nionFind?????¨ */
const int INF = 1<<28;
class UnionFindW {
    int[] parent;
    int[] value;
    this(int N) {
        parent = new int[N + 1]; parent[] = -1;
        value = new int[N + 1];
    }
    alias P = Tuple!(int, "index", int, "dist");
    /* 
     * root :: ??§?????????????????£??§?????§??? -> (???????????????????????§?????????????????£??§?????§???, ??????????????????????????????????±¬)
     */
    P root(int x) {
        if (parent[x] == -1) return P(x, 0);
        int p = parent[x];
        int v = value[x];
        P proot = root(p);
        parent[x] = proot.index;
        value[x] = v + proot.dist;
        return P(parent[x], value[x]);
    }
    /* 
     * query :: (??§?????????????????£??§?????§???x, ??§?????????????????£??§?????§???y) -> y?????¨x????????????
     */
    int query(int x, int y) {
        P xroot = root(x),
          yroot = root(y);
        if (xroot.index != yroot.index) return INF;
        return yroot.dist - xroot.dist;
    }
    /*
     * merge :: (??§?????????????????£??§?????§???x, ??§?????????????????£??§?????§???y, y?????¨x????????????w(=y-x)) -> ()
     *
     * x?????¨y??????????????§?????????????????£?????????????¬??????????????????????,?????´??????????????£?????§???????????£????????°?????°??¶?????¨?????????     */
    void merge(int x, int y, int w) {
        P 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.dist, dy = yroot.dist;
        /* 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;
    bool input() {
        readf("%d %d\n", &N, &M);
        if (N == 0 && M == 0) return false;
        return true;
    }
    void solve() {
        auto uf = new UnionFindW(N);
        foreach (_; 0 .. M) {
            auto input = readln.chomp.split(" ").array;
            int a = input[1].to!int;
            int b = input[2].to!int;
            if (input[0] == "!") {
                int w = input[3].to!int;
                uf.merge(a, b, w);
            } else { assert(input[0] == "?");
                int ans = uf.query(a, b);
                if (ans == INF) {
                    writeln("UNKNOWN");
                } else {
                    writeln(ans);
                }
            }
        }
    }
    while (input()) solve();
}