#include <bits/stdc++.h>
 
using namespace std;
 
#define SZ(x) (int)(x.size())
 
using ll = long long;
using ld = long double;
using P = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;
const double eps = 1e-10;
const int MOD = 1000000007;
const int INF = 1000000000;
const ll LINF = 1ll<<50;
 
template<typename T>
void printv(const vector<T>& s) {
  for(int i=0;i<(int)(s.size());++i) {
    cout << s[i];
    if(i == (int)(s.size())-1) cout << endl;
    else cout << " ";
  }
}
 
template< typename T >
struct edge {
  int src, to;
  T cost;
 
  edge(int to, T cost) : src(-1), to(to), cost(cost) {}
 
  edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}
 
  edge &operator=(const int &x) {
    to = x;
    return *this;
  }
 
  operator int() const { return to; }
};
 
template< typename T >
using Edges = vector< edge< T > >;
template< typename T >
using WeightedGraph = vector< Edges< T > >;
using UnWeightedGraph = vector< vector< int > >;
template< typename T >
using Matrix = vector< vector< T > >;
 
template< typename T >
vector< T > dijkstra(WeightedGraph< T > &g, int s) {
  const auto INF = numeric_limits< T >::max();
  vector< T > dist(g.size(), INF);
 
  using Pi = pair< T, int >;
  priority_queue< Pi, vector< Pi >, greater< Pi > > que;
  dist[s] = 0;
  que.emplace(dist[s], s);
  while(!que.empty()) {
    T cost;
    int idx;
    tie(cost, idx) = que.top();
    que.pop();
    if(dist[idx] < cost) continue;
    for(auto &e : g[idx]) {
      auto next_cost = cost + e.cost;
      if(dist[e.to] <= next_cost) continue;
      dist[e.to] = next_cost;
      que.emplace(dist[e.to], e.to);
    }
  }
  return dist;
}
 
template< typename G >
struct LowLink {
  const G &g;
  vector< int > used, ord, low;
  vector< int > articulation;
  vector< pair< int, int > > bridge;
 
  LowLink(const G &g) : g(g) {}
 
  int dfs(int idx, int k, int par) {
    used[idx] = true;
    ord[idx] = k++;
    low[idx] = ord[idx];
    bool is_articulation = false;
    int cnt = 0;
    for(auto &to : g[idx]) {
      if(!used[to]) {
        ++cnt;
        k = dfs(to, k, idx);
        low[idx] = min(low[idx], low[to]);
        is_articulation |= ~par && low[to] >= ord[idx];
        if(ord[idx] < low[to]) bridge.emplace_back(minmax(idx, (int) to));
      } else if(to != par) {
        low[idx] = min(low[idx], ord[to]);
      }
    }
    is_articulation |= par == -1 && cnt > 1;
    if(is_articulation) articulation.push_back(idx);
    return k;
  }
 
  virtual void build() {
    used.assign(g.size(), 0);
    ord.assign(g.size(), 0);
    low.assign(g.size(), 0);
    int k = 0;
    for(int i = 0; i < g.size(); i++) {
      if(!used[i]) k = dfs(i, k, -1);
    }
  }
};
 
 
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(10);
 
  int n, m; cin >> n >> m;
  
  WeightedGraph<ll> g(n), revg(n);
  Edges<ll> edges;
  for(int i=0;i<m;++i) {
    int a, b; ll c; cin >> a >> b >> c;
    a--; b--;
    g[a].emplace_back(edge<ll>(a, b, c));
    revg[b].emplace_back(edge<ll>(b, a, c));
    edges.emplace_back(edge<ll>(a, b, c));
  }
 
  vector<ll> d = dijkstra(g, 0);
  vector<ll> revd = dijkstra(revg, 1);
 
  // printv(d);
  // printv(revd);
 
  ll mi = d[1];
 
  UnWeightedGraph mig(n);
  for(int i=0;i<m;++i) {
    int a = edges[i].src, b = edges[i].to;
    ll c = edges[i].cost;
    if(d[a] + c + revd[b] == mi) {
      mig[a].emplace_back(b);
      mig[b].emplace_back(a);
    }
  }
 
  LowLink<UnWeightedGraph> lowlink(mig);
  lowlink.build();
  set<P> br;
  for(const auto &e: lowlink.bridge) {
    //cout << e.first << ":" << e.second << endl;
    br.insert(e);
  }
 
  for(int i=0;i<m;++i) {
    int a = edges[i].src, b = edges[i].to;
    ll c = edges[i].cost;
 
    if(d[b] != LLONG_MAX && revd[a] != LLONG_MAX && d[b] + c + revd[a] < mi) {
      cout << "HAPPY" << endl;
    } else if(d[a] + c + revd[b] == mi) {
      //cout << a << ":" << b << endl;
      if(br.find(make_pair(a, b)) == br.end() && br.find(make_pair(b, a)) == br.end()) {
        cout << "SOSO" << endl;
      } else {
        cout << "SAD" << endl;
      }
    } else {
      cout << "SOSO" << endl;
    }
  }
}


Measured memory_bytes: 35144