// Original C++ solution (slower):
#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;

  }

  

  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.weight[a];

	  ll wb = uf.weight[b];

	  cout << wb - wa << endl;

	}

      }

    }

  }

  return 0;

}

// Optimized solution to the same problem (faster):
#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;

}


// Fastest known solution for this problem: