// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;

typedef long long int ll;

const int S = 100010;



struct UnionFind {

    vector<int> node;

    vector<ll> weight;

    UnionFind() : node(S, -1), weight(S, 0) {}

    void unite(int u, int v, ll w) {

      int ov = v, ou = u;

      u = find(u), v = find(v);

      int wa = weight[ov], wb = weight[ou];

      if(u == v) return;



        // (v テ」ツ?ョティツヲツェ) テ」ツつ?(u テ」ツ?ョティツヲツェ) テ」ツ?ォテ」ツ?、テ」ツ?ェテ」ツ?津」ツつ?

        node[u] += node[v];

        node[v] = u;

        weight[v] += w + wb - wa;

    }



    ll get_weight(int u) {

        ll ret = 0;

        while(node[u] >= 0) {

            ret += weight[u];

            u = node[u];

        }

        return ret;

    }



    int find(int u) {

      if(node[u] < 0) return u;

      int par = node[u], root = find(node[u]);

      weight[u] += weight[par];

      return node[u] = root;

    }

};



int main() {

    int N, M;

    while(cin >> N >> M, N) {

        UnionFind uf;

        for(int i=0; i<M; i++) {

            char c; cin >> c;

            if(c == '!') {

                int a, b, d; cin >> a >> b >> d;

                a--; b--;

                uf.unite(a, b, d);

            }

            else {

                int a, b; cin >> a >> b;

                a--; b--;

                if(uf.find(a) != uf.find(b)) cout << "UNKNOWN" << endl;

                else {

                    ll wa = uf.get_weight(a);

                    ll wb = uf.get_weight(b);

                    // printf("wa = %d, wb = %d\n", wa, wb);

                    cout << wb - wa << endl;

                }

            }

        }



	/*

	for(int i=0; i<N; i++) {

	  printf("%d: parent = %d, weight = %lld, value = %lld\n", i, uf.node[i], uf.weight[i], uf.get_weight(i));

	}

	*/

    }

    return 0;

}

// Faster C++ solution for the same problem (measured speedup: 3.7429601974552207x):
#include <cstdio>

#include <iostream>

#include <vector>

#include <cassert>

#include <string>

using namespace std;



struct QuickFind {

    int N;

    vector<int> i2g;

    vector< vector<int> > g2i;

    vector<long long int> weight;



    QuickFind(int N_) {

        N = N_;

        i2g.resize(N);

        g2i.resize(N);

        weight.resize(N);



        for(int i=0; i<N; i++) {

            i2g[i] = i;

            g2i[i] = vector<int>{i};

        }

    }



    bool same(int u, int v) {

        return i2g[u] == i2g[v];

    }



    // v の方が w だけ大きい

    void unite(int u, int v, int w) {

        int ru = i2g[u], rv = i2g[v];

        if(ru == rv) return;



        if(g2i[rv].size() > g2i[ru].size()) {

            swap(ru, rv);

            swap(u, v);

            w = -w;

        }



        long long int prev = weight[v];

        weight[v] = weight[u] + w;



        for(auto e : g2i[rv]) {

            i2g[e] = ru;

            long long int diff = weight[e] - prev;

            if(e != v) weight[e] = weight[v] + diff;

        }



        for(auto e : g2i[rv]) {

            g2i[ru].push_back(e);

        }

        g2i[rv].clear();

    }



    long long int query(int u, int v) {

        assert(same(u, v));

        return weight[v] - weight[u];

    }

};



int N, Q;



int main() {

    while(cin >> N >> Q, N || Q) {

        QuickFind qf(N);

        for(int i=0; i<Q; i++) {

            char query; cin >> query;

            if(query == '!') {

                int u, v, w; cin >> u >> v >> w;

                u--; v--;

                qf.unite(u, v, w);

            }

            else {

                int u, v; cin >> u >> v;

                u--; v--;

                if(qf.same(u, v)) {

                    cout << qf.query(u, v) << endl;

                }

                else {

                    cout << "UNKNOWN" << endl;

                }

            }

        }

    }

    return 0;

}