#include <bits/stdc++.h>
#define inf (long long)(1e18)
using namespace std;

using P = pair<int, int>;


#define N 100006

vector<int> G[N];

vector<P> bs;
int used[N], val[N];
int dfs(int v, int p) {
  int res = 0, cnt = 0;
  used[v] = 1; // searching
  for(int w : G[v]) {
    if(w == v) {
      // self-loop edge
      continue;
    }
    if(w == p) {
      if(cnt > 0) {
        // (p, v): multiple edges
        res += 1;
        val[w] += 1;
      }
      ++cnt;
      continue;
    }
    if(!used[w]) {
      res += dfs(w, v);
    } else if(used[w] == 1) {
      res += 1;
      val[w] += 1;
    }
  }
  used[v] = 2; // searched
  res -= val[v];

  if(p != -1 && res == 0) {
    bs.push_back(p < v ? P(p, v) : P(v, p));
  }
  return res;
}

void bridge() {
  bs.clear();
  for(int i=0; i<N; ++i) used[i] = val[i] = 0;
  dfs(0, -1);
}

int main(){
  int n,m;
  scanf("%d%d", &n, &m);
  vector<pair<int, pair<long long, int> > > g[n];
  vector<pair<int, pair<long long, int> > > invg[n];
  for(int i=0;i<m;i++){
    int a,b;
    long long c;
    scanf("%d%d%lld", &a, &b, &c);
    a--;b--;
    g[a].push_back(make_pair(b, make_pair(c, i)));
    invg[b].push_back(make_pair(a, make_pair(c, i)));
  }
  // cerr << "ok" << endl;
  for(int i=0;i<n;i++)sort(g[i].begin(), g[i].end());
  for(int i=0;i<n;i++)sort(invg[i].begin(), invg[i].end());
  long long mincost;
  vector<long long> cost(n, inf);
  vector<long long> invcost(n, inf);

  priority_queue<vector<long long>,vector<vector<long long>>,greater<vector<long long>>> pq;
  pq.push(vector<long long>({0, 0}));
  while(!pq.empty()){
    long long c = pq.top()[0];
    long long p = pq.top()[1];
    pq.pop();
    if(cost[p] < inf) continue;
    cost[p] = c;
    for(auto y : g[p]){
      pq.push(vector<long long>({c+y.second.first,y.first}));
    }
  }

  pq.push(vector<long long>({0, 1}));
  while(!pq.empty()){
    long long c = pq.top()[0];
    long long p = pq.top()[1];
    pq.pop();
    if(invcost[p] < inf) continue;
    invcost[p] = c;
    for(auto y : invg[p]){
      pq.push(vector<long long>({c+y.second.first,y.first}));
    }
  }
  // cerr << "ok" << endl;
  long long path = cost[1];

  //vector<pair<int, pair<long long, int> > > dagG[m];

  for(int i=0;i<n;i++)for(int j=0;j<g[i].size();j++){
    if(cost[i] + invcost[g[i][j].first] + g[i][j].second.first == path){
      //dagG[i].push_back(g[i][j]);
      G[i].push_back(g[i][j].first);
      G[g[i][j].first].push_back(i);
    }
  }

  int ans[m]={};

  bridge();
  // cerr << "ok" << endl;
  for(int i=0;i<bs.size();i++){
    pair<int, pair<long long, int> > tmp ;
    if(lower_bound(g[bs[i].first].begin(), g[bs[i].first].end(), make_pair(bs[i].second, make_pair(0ll, 0))) != g[bs[i].first].end()){
      tmp = *lower_bound(g[bs[i].first].begin(), g[bs[i].first].end(), make_pair(bs[i].second, make_pair(0ll, 0)));
      if(tmp.first == bs[i].second && cost[bs[i].first] + tmp.second.first + invcost[bs[i].second] == path){
        ans[tmp.second.second] = -1;
      }
    }
    if(lower_bound(g[bs[i].second].begin(), g[bs[i].second].end(), make_pair(bs[i].first, make_pair(0ll, 0))) != g[bs[i].second].end()){
      tmp = *lower_bound(g[bs[i].second].begin(), g[bs[i].second].end(), make_pair(bs[i].first, make_pair(0ll, 0)));
      if(tmp.first == bs[i].first && cost[bs[i].second] + tmp.second.first + invcost[bs[i].first] == path){
        ans[tmp.second.second] = -1;
      }
    }
  }

  for(int i=0;i<n;i++)for(int j=0;j<g[i].size();j++){
    if(ans[g[i][j].second.second] != -1){
      if(cost[g[i][j].first] + g[i][j].second.first + invcost[i] < path){
        ans[g[i][j].second.second] = 1;
      }
    }
  }
  // cerr << "ok" << endl;
  for(int i=0;i<m;i++){
    if(ans[i]==-1)printf("SAD\n");
    if(ans[i]==0)printf("SOSO\n");
    if(ans[i]==1)printf("HAPPY\n");
  }

  return 0;
}



Measured memory_bytes: 32424