// Original C++ solution (slower):
#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");

	}

	

	



}




// Optimized solution to the same problem (faster):
#include<bits/stdc++.h>

#define LL long long

#define N 200005

#define MOD 1000000007

#define bas 8741

#define pli pair<LL, int>

#define mp make_pair

#define fi first

#define se second

using namespace std;

int n, m, head[2][N], num[2], x, y, z, headb[N], cnt, low[N], dfn[N], cnt1;

const LL INF = (LL)1 << 50;

bool flag[N], flage[N << 1];

LL dis[3][N], ans, stand;

struct edge {

    int fr, to, nxt, w, id;

}a[2][N << 1], b[N << 1];

void add(int x, int y, int z, int _id) {

    a[0][++num[0]] = (edge){x, y, head[0][x], z, _id}, head[0][x] = num[0];

    a[1][++num[1]] = (edge){y, x, head[1][y], z, _id}, head[1][y] = num[1];

}

void add2(int x, int y, int z, int _id) {

    b[++cnt] = (edge){x, y, headb[x], z, _id}, headb[x] = cnt;

}

priority_queue<pli, vector<pli>, greater<pli> >q;

void sssp(int st, int type) {

    for(int i = 1; i <= n; ++i) {

        dis[st][i] = INF;

        flag[i] = 0;

    }

    dis[st][st] = 0;

    while(!q.empty()) q.pop();

    pli temp = mp(0, st);

    q.push(temp);

    while(!q.empty()) {

        temp = q.top();

        q.pop();

        x = temp.se;

        flag[x] = 1;

        for(int e = head[type][x]; e; e = a[type][e].nxt) {

            y = a[type][e].to, z = a[type][e].w;

            if(dis[st][y] > dis[st][x] + z) {

                dis[st][y] = dis[st][x] + z;

                temp = mp(dis[st][y], y);

                q.push(temp);

            }

        }

    }

}

void dfs(int x, int f) {

    low[x] = dfn[x] = ++cnt1;

    flag[x] = 1;

    for(int e = headb[x]; e; e = b[e].nxt) {

        int k = b[e].to;

        if(!flag[k]) {

            dfs(k, x);

            low[x] = min(low[x], low[k]);

        }

        else if(k != f) {

            low[x] = min(low[x], dfn[k]);

        }

    }

}

void print(LL x, LL y) {

    if(x > y) printf("SAD\n");

    else if(x == y) printf("SOSO\n");

    else printf("HAPPY\n");

}

int main() {

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

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

        scanf("%d%d%d", &x, &y, &z);

        add(x, y, z, i);

    }

    sssp(1, 0);

    sssp(2, 1);

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

        x = a[0][i].fr, y = a[0][i].to;

        if(dis[1][x] + a[0][i].w == dis[1][y] && dis[2][y] + a[0][i].w == dis[2][x]) {

            add2(x, y, z, i);

            add2(y, x, z, i);

            flage[i] = 1;

        }

    }

    for(int i = 1; i <= n; ++i) flag[i] = 0;

    dfs(1, 0);

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

        if(!flage[i]) continue;

        x = a[0][i].fr, y = a[0][i].to;

        if(low[y] <= dfn[x]) flage[i] = 0;

    }

    stand = dis[1][2];

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

        x = a[0][i].fr, y = a[0][i].to;

        if(flage[i]) {

            ans = dis[1][y] + a[0][i].w + dis[2][x];

            print(ans, stand);

        }

        else {

            ans = min(stand, dis[1][y] + a[0][i].w + dis[2][x]);

            print(ans, stand);

        }

    }

    return 0;

}




// Fastest known solution for this problem: