#include <cassert>
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#define rep(i,n) for(int i = 0 ; i < (int)(n) ; i++)
#define INF 1e15
#define int long long

struct Edge{
	int a,b,c, id;
};

struct Node{
	int p,c;
};

bool operator < (Node a,Node b){
	return a.c > b.c;
}

vector<int> dijkstra(int s, vector< vector<Edge> > g){
	vector<int> dist(g.size(), INF);
	priority_queue<Node> Q;
	Q.push({s,0});
	while( Q.size() ){
		auto q = Q.top(); Q.pop();
		if( dist[q.p] != INF ) continue;
		dist[q.p] = q.c;
		for( auto e : g[q.p] ){
			Q.push({e.b, q.c + e.c});
		}
	}
	return dist;
}

int visited[100010];
int currentTime = 0;

set<int> bridges;

map< pair<int,int> , int> counter;

int dfs(int x, int p, const vector< vector<Edge> > &g){
	currentTime++;
	visited[x] = currentTime;

	int ans = currentTime;
	for( auto &&e : g[x] ){
		if( e.b == p ) continue;

		if( visited[e.b] != 0 ){
			ans = min(ans, visited[e.b]);
		}else{
			ans = min(ans, dfs(e.b, x, g));
		}
	}
	if( p != -1 && ans > visited[p]){
	
		counter[{x, p}]++;
		counter[{p, x}]++;
	}
	return ans;
}

signed main(){
	int n,m;
	cin >> n >> m;
	vector<Edge> es;
	vector< vector<Edge> > g(n),rg(n);
	for(int i = 0 ; i < m ; i++){
		int a,b,c;
		cin >> a >> b >> c;
		--a,--b;
		es.push_back({a,b,c, i});
		g[a].push_back({a,b,c, i});
		rg[b].push_back({b,a,c, i});
	}

	int S = 0;
	int G = 1;
	auto gDist = dijkstra(S, g);
	auto rgDist = dijkstra(G, rg);
	
	vector< vector<Edge> > dag(n);
	for( auto e : es ){
		if( gDist[e.a] + e.c + rgDist[e.b] == gDist[G] ){
			dag[e.a].push_back(e);
			dag[e.b].push_back({e.b,e.a,e.c,e.id});
		}
	}
	dfs(0, -1, dag);

	for( auto e : es ){
		if( gDist[e.b] + e.c + rgDist[e.a] < gDist[G] ){
			cout << "HAPPY" << endl;
		}else if( gDist[e.a] + e.c + rgDist[e.b] != gDist[G] ){
			cout << "SOSO" << endl;
		}else if( counter[{e.a,e.b}] != 1 ){
			cout << "SOSO" << endl;
		}else{
			cout << "SAD" << endl;
		}
	}
}

Measured memory_bytes: 56492