#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> i_i;

vector< pair<int, int> > lowlink(const vector< vector<int> >& g) {
    int n = g.size();
    vector<int> ord(n, -1), low(n, -1);
    vector < pair<int, int> > bridges;
    int t = 0;
    auto dfs = [&](auto& F, int v, int p) -> void {
        ord[v] = low[v] = t++;
        int d = 0;
        bool f = false;
        for (int w : g[v]) if (w != p) {
            if (ord[w] == -1) {
                F(F, w, v);
                low[v] = min(low[v], low[w]);
                f |= ord[v] <= low[w];
                if (ord[v] < low[w]) bridges.emplace_back(minmax(v, w));
                ++d;
            } else {
                low[v] = min(low[v], ord[w]);
            }
        }
    };
    dfs(dfs, 0, -1);
    sort(begin(bridges), end(bridges));
    return bridges;
}

typedef pair<ll, ll> l_l;
vector<l_l> paths[100500][2];
ll N, M;
ll dist[100500][2];
ll a[100500], b[100500], c[100500];
vector<vector<int>> G;
vector<l_l> costs[100500];
bool chmin(ll &a, ll b) {
    if(a > b) {
        a = b;
        return true;
    }
    return false;
}
void Dijkstra(int s, int index) {
    for(int i = 0; i < N; i++) {
        dist[i][index] = 1e18;
    }
    dist[s][index] = 0;
    priority_queue<l_l, vector<l_l>, greater<l_l>> que;
    que.push({0, s});
    while(!que.empty()) {
        l_l now = que.top();
        que.pop();
        ll pos = now.second;
        ll nowcost = now.first;
        if(now.first != dist[pos][index]) continue;
        for(auto e : paths[pos][index]) {
            ll newcost = nowcost + e.second;
            ll to = e.first;
            if(chmin(dist[to][index], newcost)) {
                que.push({newcost, to});
            }
        }
    }
}

int main() {
    cin >> N >> M;
    for(int i = 0; i < M; i++) {
        cin >> a[i] >> b[i] >> c[i];
        a[i]--;
        b[i]--;
        paths[a[i]][0].push_back({b[i], c[i]});
        paths[b[i]][1].push_back({a[i], c[i]});
    }
    Dijkstra(0, 0);
    Dijkstra(1, 1);
    /*
    for(int i = 0; i < N; i++) {
        for(auto e : paths[i][0]) {
            ll to = e.first;
            ll cost = dist[i][0] + e.second + dist[to][1];
            costs[i].push_back({cost, to});
        }
        sort(costs[i].begin(), costs[i].end());
        cerr << "--" << i << "---" << endl;
        for(auto val : costs[i]) {
            cerr << val.second << " " << val.first << endl;
        }
    }
    */
   /*
    ll Default = dist[2][0];
    for(int i = 1; i <= M; i++) {
        if(cost[i])
        ll ans = 2e18;
        ll now = dist[b[i]][0];
        now += c[i];
        now += dist[a[i]][1];
        chmin(ans, now);

    }
    */
    //for(int i = 0; i < N; i++) cerr << dist[i][0] << endl;
    //for(int i = 0; i < N; i++) cerr << dist[i][1] << endl;
    G.resize(N);
    for(int i = 0; i < M; i++) {
        ll nowcost = dist[a[i]][0] + c[i] + dist[b[i]][1];
        if(nowcost == dist[1][0]) {
            G[a[i]].push_back(b[i]);
            G[b[i]].push_back(a[i]);
            //cerr << a[i] << " " << b[i] << endl;
        }
    }
    vector< pair<int, int> > bridges = lowlink(G);
    set<i_i> st;
    st.insert({-1, -1});
    for(auto e : bridges) {
        st.insert(e);
        swap(e.first, e.second);
        st.insert(e);
        //cerr << e.first << " " << e.second << endl;
    }
    for(int i = 0; i < M; i++) {
        ll newcost = dist[b[i]][0] + c[i] + dist[a[i]][1];
        if(newcost < dist[1][0]) {
            cout << "HAPPY" << endl;
            continue;
        }
        if(newcost == dist[1][0]) {
            cout << "SOSO" << endl;
            continue;
        }
        if(dist[a[i]][0] + c[i] + dist[b[i]][1] == dist[0][1]) {
            if(st.find({a[i], b[i]}) != st.end()) {
                cout << "SAD" << endl;
                continue;
            }
        }
        cout << "SOSO" << endl;
    }
}


Measured memory_bytes: 40128