#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long int lli;
const lli inf = 1e18;

vector<lli> shortest_path(int from, vector<vector<pair<int,lli>>> &graph){
    int n = graph.size();
    vector<lli> mincost(n, inf);
    mincost[from] = 0;
    priority_queue<pair<lli,int>> wait;
    wait.push({0LL, from});
    while(!wait.empty()){
        lli cost = -wait.top().first;
        int pos = wait.top().second;
        wait.pop();
        if(cost > mincost[pos]) continue;
        for(auto next: graph[pos]){
            lli ncost = cost + next.second;
            int npos = next.first;
            if(ncost < mincost[npos]){
                mincost[npos] = ncost;
                wait.push({-ncost, npos});
            }
        }
    }
    return mincost;
}

int bridges_dfs(int curr, int prev, int &count,
                vector<int> &pre, vector<int> &low,
                vector<pair<int,int>> &res, vector<vector<int>> &graph){
    if(pre[curr] != -1) return low[curr];
    pre[curr] = count++;
    low[curr] = pre[curr];
    for(int next: graph[curr]){
        if(next == prev) continue;
        int ret = bridges_dfs(next, curr, count, pre, low, res, graph);
        if(ret > pre[curr]){
            res.emplace_back(curr, next);
        }
        low[curr] = min(low[curr], ret);
    }
    return low[curr];
}
vector<pair<int,int>> bridges(vector<vector<int>> &graph){
    int n = graph.size();
    vector<pair<int,int>> res;
    vector<int> pre(n, -1), low(n);
    int count = 0;
    bridges_dfs(0, -1, count, pre, low, res, graph);
    return res;
}
set<pair<int,int>> bridge_list(vector<vector<pair<int,lli>>> &graph, vector<lli> &mincost_s, vector<lli> &mincost_t){
    int n = graph.size();
    vector<vector<int>> adj(n);
    for(int i=0; i<n; i++){
        for(auto next: graph[i]){
            int j = next.first;
            int cost = next.second;
            if(mincost_s[1] == mincost_s[i] +cost +mincost_t[j]){
                adj[i].push_back(j);
                adj[j].push_back(i);
            }
        }
    }
    for(auto &v: adj){
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
    }
    auto ret = bridges(adj);
    set<pair<int, int>> res;
    for(auto p: ret){
        if(mincost_s[p.first] < mincost_s[p.second]){
            res.insert(p);
        }else{
            res.insert({p.second, p.first});
        }
    }
    return res;
}

int main(){
    int n,m;
    cin >> n >> m;
    vector<int> a(m),b(m),c(m);
    map<pair<int,int>, int> minedge, duality;
    vector<vector<pair<int, lli>>> adj(n), adjrev(n);
    for(int i=0; i<m; i++){
        cin >> a[i] >> b[i] >> c[i];
        a[i]--; b[i]--;
        adj[a[i]].emplace_back(b[i], c[i]);
        adjrev[b[i]].emplace_back(a[i], c[i]);
        pair<int, int> pab(a[i], b[i]);
        if(minedge.count(pab) == 0){
            minedge[pab] = c[i];
        }else{
            minedge[pab] = min(minedge[pab], c[i]);
        }
    }
    for(int i=0; i<m; i++){
        pair<int, int> pab(a[i], b[i]);
        if(minedge[pab] == c[i]){
            duality[pab]++;
        }
    }
    int s=0, t=1;
    auto sp_s = shortest_path(s, adj);
    auto sp_t = shortest_path(t, adjrev);
    auto bridge = bridge_list(adj, sp_s, sp_t);
    for(int i=0; i<m; i++){
        pair<int, int> pab(a[i], b[i]);
        if(sp_s[b[i]] +c[i] +sp_t[a[i]] < sp_s[t]){
            cout << "HAPPY" << endl;
        }else if(bridge.find(pab)==bridge.end() or minedge[pab]!=c[i] or duality[pab]>1){
            cout << "SOSO" << endl;
        }else{
            cout << "SAD" << endl;
        }
    }
    return 0;
}



Measured memory_bytes: 51004