#include <bits/stdc++.h>
using namespace std;

#define INF_LL (int64)1e18
#define INF (int64)1e9
#define REP(i, n) for(int64 i = 0; i < (n); i++)
#define FOR(i, a, b) for(int64 i = (a); i < (b); i++)
#define all(x) x.begin(),x.end()
#define fs first
#define sc second

using int32 = int_fast32_t;
using uint32 = uint32_t;
using int64 = int64_t;
using uint64 = uint64_t;
using PII = pair<int32, int32>;
using PLL = pair<int64, int64>;

template<typename A, typename B> inline void chmin(A &a, B b) { if (a > b) a = b; }
template<typename A, typename B> inline void chmax(A &a, B b) { if (a < b) a = b; }

const int32 DIRECTED = 0;
const int32 UNDIRECTED = 1;
template<int32 isUNDIRECTED=0>
class Graph {
public:
  struct Edge {
    int32 u, v, id;
    int64 c;
    Edge(int32 u, int32 v, int64 c = 0, int32 id=0): u(u), v(v), c(c), id(id) {}
  };
  int32 V, E;
  vector<vector<Edge>> G;
  vector<Edge> Es;
public:
  Graph() {}
  Graph(int32 V):V(V) { G.resize(V); }
  Graph(const Graph<isUNDIRECTED>& g): V(g.V), E(g.E), G(g.G), Es(g.Es) {}

  void add_edge(int32 u, int32 v, int64 c = 0, int32 id = 0) {
    G[u].emplace_back(u, v, c, id);
    if (isUNDIRECTED) G[v].emplace_back(v, u, c, id);
    E++;
  }

  const vector<Edge>& operator[](int32 k) {
    return G[k];
  }
};

template<int isUNDIRECTED=1>
class Lowlink : public Graph<isUNDIRECTED> {
  vector<int32> ord, low;
  vector<int32> articulation;
  vector<pair<int32, int32>> bridge;
public:
  Lowlink() {}
  Lowlink(int32 V): Graph<isUNDIRECTED>(V) {}

  void build() {
    ord.resize(this->V, -1);
    low.resize(this->V, -1);
    int32 k = 0;

    function<void(int32, int32)> dfs = [&, this](int32 v, int32 p) {
      ord[v] = k++;
      low[v] = ord[v];
      bool isArt = 0;
      int32 cnt = 0;

      for (auto &e : this->G[v]) {
        if (e.v == p) continue;
        if (ord[e.v] == -1) {
          cnt++;
          dfs(e.v, v);
          low[v] = min(low[v], low[e.v]);
          if (~p && ord[v] <= low[e.v]) isArt = 1;
        } else {
          low[v] = min(low[v], ord[e.v]);
        }
      }
      if (p == -1 && cnt > 1) isArt = 1;
    };
    for (int32 i = 0; i < this->V; i++)
      if (ord[i] == -1) dfs(i, -1);
  }

  const vector<pair<int32, int32>>& getBridge() {
    return bridge;
  }

  const vector<int32>& getArticulation() {
    return articulation;
  }

  bool isBridge(int32 u, int32 v) const {
    if (ord[u] > ord[v]) swap(u, v);
    return ord[u] < low[v];
  }
};

int64 n, m;
vector<vector<PLL>> G, rG;

int main(void) {
  cin >> n >> m;
  G.resize(n); rG.resize(n);
  using T = tuple<int64, int64, int64>;
  vector<T> es(m);
  REP(i, m) {
    int64 a, b, c;
    cin >> a >> b >> c; a--; b--;
    G[a].emplace_back(c, b);
    rG[b].emplace_back(c, a);
    es[i] = T(a, b, c);
  }

  vector<int64> d, rd;

  auto dijkstra = [&](const vector<vector<PLL>>& G, int64 st, vector<int64>& d) {
    d = vector<int64>(n, INF_LL);
    d[st] = 0;
    priority_queue<PLL, vector<PLL>, greater<PLL>> pq;
    pq.emplace(0, st);
    while (pq.size()) {
      int64 v, c;
      tie(c, v) = pq.top(); pq.pop();
      if (c > d[v]) continue;
      for (auto &e : G[v]) {
        if (e.fs + c < d[e.sc]) {
          d[e.sc] = e.fs + c;
          pq.emplace(d[e.sc], e.sc);
        }
      }
    }
  };
  dijkstra(G, 0, d); dijkstra(rG, 1, rd);
  Lowlink<> low(n);
  queue<PLL> q;
  q.emplace(d[1], 1);
  vector<int> used(n, 0);
  while (q.size()) {
    int64 v, c;
    tie(c, v) = q.front(); q.pop();
    for (auto &e : rG[v]) {
      if (c - e.fs == d[e.sc]) {
        low.add_edge(e.sc, v);
        if (!used[e.sc])
          q.emplace(d[e.sc], e.sc);
        used[e.sc] = 1;
      }
    }
  }
  low.build();

  REP(i, m) {
    int64 u, v, c;
    tie(u, v, c) = es[i];
    if (d[v] + rd[u] + c < d[1]) {
      cout << "HAPPY" << endl;
      continue;
    } else if (low.isBridge(u, v) && d[u] + c == d[v] && d[v] + rd[v] == d[1]){
      cout << "SAD" << endl;
    } else {
      cout << "SOSO" << endl;
    }
  }
}



Measured memory_bytes: 37660