#include <map>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
const int mod = 1000000021;
const long long inf = 1LL << 61;
struct edge { int to, cost, id; };
struct edge2 { int to, id; };
struct state { int pos; long long cost; };
bool operator<(const state& s1, const state& s2) { return s1.cost > s2.cost; }
int N, M, dp[100009], dp2[100009], va[100009]; bool vis1[100009], vis2[100009]; vector<int> a, b, c;
vector<long long> shortest_path(vector<vector<edge> > g, int src) {
	vector<long long> ret(g.size(), inf); ret[src] = 0;
	priority_queue<state> que; que.push(state{ src, 0 });
	while (!que.empty()) {
		int u = que.top().pos; que.pop();
		for (edge e : g[u]) {
			long long nd = ret[u] + e.cost;
			if (ret[e.to] > nd) {
				ret[e.to] = nd;
				que.push(state{ e.to, nd });
			}
		}
	}
	return ret;
}
vector<int> solve() {
	vector<vector<edge> > g(N);
	vector<vector<edge> > rg(N);
	for (int i = 0; i < M; i++) {
		g[a[i]].push_back(edge{ b[i], c[i], i });
		rg[b[i]].push_back(edge{ a[i], c[i], i });
	}
	vector<long long> ds = shortest_path(g, 0);
	vector<long long> dt = shortest_path(rg, 1);
	vector<bool> ok(M);
	vector<vector<edge2> > sg(N), sr(N);
	for (int i = 0; i < M; i++) {
		if (ds[a[i]] + c[i] + dt[b[i]] == ds[1]) {
			sg[a[i]].push_back(edge2{ b[i], i });
			sr[b[i]].push_back(edge2{ a[i], i });
			ok[i] = true;
		}
	}
	fill(vis1, vis1 + N, false);
	fill(vis2, vis2 + N, false);
	fill(dp, dp + N, 0);
	fill(dp2, dp2 + N, 0);
	vector<int> dpm1(M), dpm2(M);
	priority_queue<state> que; que.push(state{ 0, 0 }); dp[0] = 1;
	while (!que.empty()) {
		int u = que.top().pos; que.pop();
		if (!vis1[u]) {
			vis1[u] = true;
			for (edge2 i : sg[u]) {
				dp[i.to] += dp[u];
				dpm1[i.id] = dp[u];
				if (dp[i.to] >= mod) dp[i.to] -= mod;
				que.push(state{ i.to, ds[i.to] });
			}
		}
	}
	que.push(state{ 1, 0 }); dp2[1] = 1;
	while (!que.empty()) {
		int u = que.top().pos; que.pop();
		if (!vis2[u]) {
			vis2[u] = true;
			for (edge2 i : sr[u]) {
				dp2[i.to] += dp2[u];
				dpm2[i.id] = dp2[u];
				if (dp2[i.to] >= mod) dp2[i.to] -= mod;
				que.push(state{ i.to, dt[i.to] });
			}
		}
	}
	for (int i = 0; i < N; i++) va[i] = 1LL * dp[i] * dp2[i] % mod;
	map<tuple<int, int, int>, int> cnts;
	for (int i = 0; i < M; i++) {
		cnts[make_tuple(a[i], b[i], c[i])]++;
	}
	vector<int> ret(M);
	for (int i = 0; i < M; i++) {
		if (!ok[i]) {
			ret[i] = (ds[b[i]] + dt[a[i]] + c[i] < ds[1] ? 2 : 1);
		}
		else {
			if (ds[b[i]] + dt[a[i]] + c[i] < ds[1]) ret[i] = 2;
			else if (ds[b[i]] + dt[a[i]] + c[i] == ds[1]) ret[i] = 1;
			else {
				if (1LL * dpm1[i] * dpm2[i] % mod == va[0] && cnts[make_tuple(a[i], b[i], c[i])] == 1) ret[i] = 0;
				else ret[i] = 1;
			}
		}
	}
	return ret;
}
int main() {
	ios::sync_with_stdio(false);
	cin >> N >> M;
	a = vector<int>(M);
	b = vector<int>(M);
	c = vector<int>(M);
	for (int i = 0; i < M; i++) {
		cin >> a[i] >> b[i] >> c[i]; a[i]--, b[i]--;
	}
	vector<int> ret = solve();
	for (int i = 0; i < M; i++) {
		if (ret[i] == 2) cout << "HAPPY\n";
		else if (ret[i] == 1) cout << "SOSO\n";
		else cout << "SAD\n";
	}
	return 0;
}