// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;



const long long inf = 0x3f3f3f3f3f3f3f3fLL;

typedef pair<int, int> PII;

typedef unsigned int uint;

typedef unsigned long long uLL;



const int N = 1e5 + 10;



int n, m;



vector<PII> adj[N], radj[N];



uLL cnt1[N], cnt2[N];

long long dis1[N], dis2[N];



struct node {

	int u, v; long long dis;

	node (int u = 0, int v = 0, long long dis = 0)

		:u(u), v(v), dis(dis) {}

	bool operator < (const node &rhs) const {

		return dis > rhs.dis;

	}

};



vector<node> E;



int main() {

	int n, m; scanf("%d%d", &n, &m);

	for (int i = 0; i < m; i++) {

		int u, v, w; scanf("%d%d%d", &u, &v, &w);

		adj[u].push_back(make_pair(v, w));

		radj[v].push_back(make_pair(u, w));

		E.push_back(node(u, v, w));

	}



	memset (dis1, 0x3f, sizeof dis1);

	memset (dis2, 0x3f, sizeof dis2);

	//count all shortest route from 1 to other nodes

	priority_queue<node> pq;

	pq.push(node(0, 1, 0));

	cnt1[0] = 1;

	while (!pq.empty()) {

		node cur = pq.top(); pq.pop();

		if (dis1[cur.v] < cur.dis) continue;

		if (dis1[cur.v] == cur.dis) {

			cnt1[cur.v] += cnt1[cur.u];

			continue;

		}

		dis1[cur.v] = cur.dis;

		cnt1[cur.v] = cnt1[cur.u];

		for (int i = 0; i < adj[cur.v].size(); i++) {

			long long d = dis1[cur.v] + adj[cur.v][i].second;

			if (dis1[adj[cur.v][i].first] >= d) 

				pq.push(node(cur.v, adj[cur.v][i].first, d));

		}

	}



	assert (pq.empty() == true);

	//count all shortest route from 2 to other nodes

	pq.push(node(0, 2, 0));

	cnt2[0] = 1;

	while (!pq.empty()) {

		node cur = pq.top(); pq.pop();

		if (dis2[cur.v] < cur.dis) continue;

		if (dis2[cur.v] == cur.dis) {

			cnt2[cur.v] += cnt2[cur.u];

			continue;

		}

		dis2[cur.v] = cur.dis;

		cnt2[cur.v] = cnt2[cur.u];

		for (int i = 0; i < radj[cur.v].size(); i++) {

			long long d = dis2[cur.v] + radj[cur.v][i].second;

			if (dis2[radj[cur.v][i].first] >= d) 

				pq.push(node(cur.v, radj[cur.v][i].first, d));

		}

	}



	long long shortdis = dis1[2];

	for (int i = 0; i < E.size(); i++) {

		if (i == 5)

			i = i;

		node cur = E[i];

		long long newdis = dis1[cur.v] + dis2[cur.u] + cur.dis;

		if (shortdis > dis1[cur.v] + dis2[cur.u] + cur.dis) {

			puts("HAPPY");

		} else if (shortdis == newdis) {

			puts("SOSO");

		} else if (shortdis < dis1[cur.u] + dis2[cur.v] + cur.dis) {

			puts("SOSO");

		} else if (cnt1[cur.u] * cnt2[cur.v] == cnt1[2]) {

			puts("SAD");

		} else {

			puts("SOSO");

		}

	}



	return 0;

}

/*

4 5

1 3 5

3 4 6

4 2 7

2 1 18

3 2 13

*/	


// Faster C++ solution for the same problem (measured speedup: 1.2768809999779311x):
#include <bits/stdc++.h>



using namespace std;



const int maxn = 100000;

const int maxm = 100000;



class Node

{

public:

	int u;

	long long d;



	Node(void);

	Node(const int &, const long long &);



	bool operator < (const Node &) const;

};



class Edge

{

public:

	int u;

	int v;

	int w;



	Edge(void);

	Edge(const int &, const int &, const int &);

};



Node::Node(void) : u(0), d(0)

{



}



Node::Node(const int & u, const long long & d) : u(u), d(d)

{



}



bool Node::operator < (const Node & rhs) const

{

	return d > rhs.d;

}



Edge::Edge(void) : u(0), v(0), w(0)

{



}



Edge::Edge(const int & u, const int & v, const int & w) : u(u), v(v), w(w)

{



}



int n, m;

vector<Edge> E;

vector<int> Eid[maxn];

vector<Edge> Et;

vector<int> Etid[maxn];

long long d[maxn];

long long deg[maxn];

long long dt[maxn];

long long degt[maxn];



void dijkstra(const int & s, vector<Edge> & E, vector<int> Eid[], long long d[], long long deg[])

{

	Node cur, tgt;

	priority_queue<Node> que;



	memset(d, 0x3f, sizeof(d[0]) * n);

	memset(deg, 0, sizeof(deg[0]) * n);

	d[s] = 0;

	deg[s] = 1;

	for (que.push(Node(s, 0)); !que.empty(); )

	{

		cur = que.top();

		que.pop();



		if (d[cur.u] < cur.d)

			continue;



		int u = cur.u, v, w;

		for (int i = 0; i < Eid[u].size(); ++ i)

		{

			v = E[Eid[u][i]].v;

			w = E[Eid[u][i]].w;

			if (d[v] > d[u] + w)

			{

				d[v] = d[u] + w;

				deg[v] = deg[u];

				que.push(Node(v, d[v]));

			}

			else if (d[v] == d[u] + w)

				deg[v] += deg[u];

		}

	}

}



inline int check_edge(const int & idx)

{

	if (d[E[idx].v] + E[idx].w + dt[E[idx].u] < d[1])

		return -1;

	else if (d[E[idx].u] + E[idx].w + dt[E[idx].v] == d[1] && deg[E[idx].u] * degt[E[idx].v] == deg[1])

		return 1;

	else

		return 0;

}



int main()

{

	ios_base::sync_with_stdio(false);



	cin >> n >> m;

	for (int i = 0; i < m; ++ i)

	{

		int u, v, w;



		cin >> u >> v >> w;

		-- u;

		-- v;

		E.push_back(Edge(u, v, w));

		Eid[u].push_back(i);

		Et.push_back(Edge(v, u, w));

		Etid[v].push_back(i);

	}



	dijkstra(0, E, Eid, d, deg);

	dijkstra(1, Et, Etid, dt, degt);



	int ans;

	for (int k = 0; k < m; ++ k)

	{

		ans = check_edge(k);



		if (ans == -1)

			cout << "HAPPY";

		else if (ans == 0)

			cout << "SOSO";

		else

			cout << "SAD";

		cout << endl;

	}



	return 0;

}