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

#define int long long

struct BiconectedGraph{  
  typedef pair<int,int> P;  
  int n;  
  vector<vector<int> > G,C,T;
  vector<int> ord,low,belong;
  vector<P> B;
  BiconectedGraph(){};
  BiconectedGraph(int sz):n(sz),G(sz),C(sz),T(sz){};
   
  void add_edge(int u,int v){
    G[u].push_back(v);
    G[v].push_back(u);
  }
   
 
  bool is_bridge(int u,int v){
    if(ord[u] > ord[v]) swap(u,v);
    return ord[u] < low[v];
  }
 
  void dfs(int u,int p,int &k){
    ord[u] = low[u] = k;
    ++k;
    for(int v:G[u]){
      if(v == p) continue;
      if(ord[v] >=0){
    low[u] = min(low[u],ord[v]);
      } else {
    dfs(v,u,k);
    low[u] = min(low[u],low[v]);
      }
      if(is_bridge(u,v)) B.push_back(P(u,v));
    }
  }
   
  void fill_component(int c,int u){
    C[c].push_back(u);
    belong[u] = c;
    for(int v:G[u]){
      if(belong[v] >= 0 || is_bridge(u,v)) continue;
      fill_component(c,v);
    }
  }
   
  void add_component(int u,int &k){
    if(belong[u] >=0) return;
    fill_component(k++,u);
  }
   
  int build(){
    int k = 0;
    ord.resize(n);
    low.resize(n);
    belong.resize(n);
    fill(ord.begin(),ord.end(),-1);
    fill(belong.begin(),belong.end(),-1);
    for(int u=0;u<n;u++){
      if(ord[u] >= 0) continue;
      dfs(u,-1,k);
    }
    k = 0;
    for(int i=0;i<(int)B.size();i++){
      add_component(B[i].first,k);
      add_component(B[i].second,k);
    }
     
    for(int u=0;u<n;u++) add_component(u,k);
    for(int i=0;i<(int)B.size();i++){
      int u = belong[B[i].first], v = belong[B[i].second];
      T[u].push_back(v);
      T[v].push_back(u);
    }
    return k;
  }
};

template <typename T>
vector<T> dij(int s, vector<vector<pair<int, T> > > &G, T INF) {
  using P = pair<T, int>;
  int n = G.size();
  vector<T> d(n, INF);
  vector<int> b(n, -1);
  priority_queue<P, vector<P>, greater<P> > q;
  d[s] = 0;
  q.emplace(d[s], s);  
  while ( !q.empty() ) {
    P p = q.top(); q.pop();
    int v = p.second;
    if ( d[v] < p.first ) continue;
    for ( auto& e : G[v] ) {
      int u = e.first;
      T c = e.second;
      if ( d[u] > d[v]+c ) {
	d[u] = d[v]+c;
	b[u] = v;
	q.emplace(d[u], u);	
      }
    }
  }
  
  return d;
}

struct Edge {
  int u, v, c;  
};

typedef pair<int, int> P;

signed main() {
  int n, m;
  cin >> n >> m;
  
  vector<vector<pair<int, int> > > G(n), bG(n);
  vector<Edge> edges(m);  
  for ( int i = 0; i < m; i++ ) {
    int u, v, c;
    cin >> u >> v >> c;
    u--; v--;
    edges[i] = {u, v, c};    
    G[u].emplace_back(P(v, c));
    bG[v].emplace_back(P(u, c));
  }

  vector<int> d = dij<int>(0, G, (int)1e13);  
  vector<int> bd = dij<int>(1, bG, (int)1e13);
  int mi = d[1];  

  BiconectedGraph ll(n);  
  int used[100001] = {};  
  for ( int i = 0; i < m; i++ ) {
    int u = edges[i].u, v = edges[i].v, c = edges[i].c;    
    if ( d[u]+bd[v]+c == mi ) {
      ll.add_edge(u, v);
      used[i] = true;      
    }
  }

  ll.build();  

  for ( int i = 0; i < m; i++ ) {
    int u = edges[i].u, v = edges[i].v, c = edges[i].c;
    int nc = d[v]+bd[u]+c;        
    if ( nc < mi ) {
      cout << "HAPPY" << endl;
    } else if ( !used[i] || nc == mi ) {      
      cout << "SOSO" << endl;      
    } else {
      if ( ll.is_bridge(u, v) ) cout << "SAD" << endl;
      else cout << "SOSO" << endl;      
    }
  }

  return 0;
}


