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

using namespace std;

typedef long long ll;

typedef pair<ll,ll> P;

ll V,E;

struct edge{

	ll to,cost,id;

};

const ll maxn = 100005;

const ll INF = 102120027425345LL;

vector<edge> G[maxn],rG[maxn],sG[maxn];

ll d[maxn], d2[maxn];

bool isBridge[maxn];

void dijkstra(ll s, vector<edge> G[maxn], ll d[maxn]) {

	priority_queue<P, vector<P>, greater<P> > que;

	fill(d, d+V, INF);

	d[s] = 0;

	que.push(P(0,s));

	while (!que.empty()) {

		P p = que.top(); que.pop();

		ll v = p.second;

		if (d[v] < p.first) continue;

		for (auto e:G[v]){

			if (d[e.to] > d[v] + e.cost) {

				d[e.to] = d[v] + e.cost;

				que.push(P(d[e.to],e.to));

			}			

		}

	}

}

	map<P,ll> M;

ll dfs_clock,pre[maxn],low[maxn];

ll dfs(ll u, ll fa) {

	ll lowu = pre[u] = ++dfs_clock;

	for (auto e: sG[u]) {

		ll v = e.to;

		if (!pre[v]) {

			ll lowv = dfs(v,u);

			lowu = min(lowu, lowv);

			if (lowv > pre[u]){

				if (M[P(u,v)]==1) isBridge[e.id] = true;

			}

		}

		else if (pre[v] <pre[u]&&fa!=v) lowu = min(lowu, pre[v]);

	}

	return low[u] = lowu;

}



ll ans[maxn];





int main() {

	scanf("%d%d", &V, &E);



	for (ll i = 0; i < E; i++) {

		ll x,y,cost;

		scanf("%lld%lld%lld",&x,&y,&cost);

		--x,--y;

		

		G[x].push_back(edge{y,cost,i});

		rG[y].push_back(edge{x,cost,i});	

	}

	dijkstra(0,G,d);

	dijkstra(1,rG,d2);

	for(ll i = 0; i < V; i++)

	for (auto e:G[i]) {

		//cerr << i << " "  <<e.to <<" " << d[i] << " " << e.cost << " " << d[e.to] << endl;

		if (d[i] + e.cost == d[e.to]&&d[e.to]+d2[e.to]==d[1]) 

		{

			sG[i].push_back(e),sG[e.to].push_back(edge{i,e.cost,e.id});//cerr << i << " "  <<e.to<<endl; 

			M[P(i,e.to)]++;

		}

	}

	//cerr << "------" << endl;

	dfs(0,-1);

	//for (ll i = 0; i < E; i++) cerr<< isBridge[i] << " " ;

	//cerr<<endl;

	for(ll i = 0; i < V; i++)

	for (auto e:G[i]) {

		if (isBridge[e.id]) ans[e.id] = -1;

		else {

			if (d[e.to] + e.cost + d2[i] < d[1]) ans[e.id] = 1;

			else ans[e.id] = 0;

		}

	}

	for (ll i = 0; i < E; i++) {

		if (ans[i] == -1) puts("SAD");

		else if (ans[i] == 0) puts("SOSO");

		else puts("HAPPY");

	}

	

	



}




// Faster C++ solution for the same problem (measured speedup: 1.1280424623876364x):
#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

*/