// 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: 2.7370901865751556x):
#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;

#define ll long long

 

const int maxn=1e5+5;

 

int n,m;

bool bo[maxn];

int a[maxn],b[maxn],c[maxn];

 

int read() {

    int x=0,f=1;char ch=getchar();

    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;

    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';

    return x*f;

}

 

struct node {

    ll v;

    int u;

 

    node() {}

     

    node(int _u,ll _v) {u=_u,v=_v;}

 

    bool operator<(const node &a)const {

        return v<a.v;

    }

};

 

struct Heap {

    int tot;

    node tree[maxn];

     

    void ins(node x) {

        tree[++tot]=x;

        int pos=tot;

        while(pos>1) {

            if(tree[pos]<tree[pos>>1])

                swap(tree[pos],tree[pos>>1]),pos>>=1;

            else break;

        }

    }

 

    int pop() {

        node res=tree[1];

        tree[1]=tree[tot--];

        int pos=1,son=2;

        while(son<=tot) {

            if(son<tot&&tree[son|1]<tree[son])son|=1;

            if(tree[son]<tree[pos])

                swap(tree[son],tree[pos]),pos=son;

            else break;son=pos<<1;

        }

        return res.u;

    }

}T;

 

struct graph {

    int tot,h,t;

    ll dis[maxn],cnt[maxn];

    int list[maxn],deg[maxn];

    int now[maxn],pre[maxn],son[maxn],val[maxn];

 

    void clear() {

        tot=0;memset(now,0,sizeof(now));

        memset(deg,0,sizeof(deg));

    }

     

    void add(int a,int b,int c) {

        pre[++tot]=now[a];

        now[a]=tot;son[tot]=b;

        val[tot]=c;deg[b]++;

    }

 

    void dij(int st) {

        memset(dis,63,sizeof(dis));

        dis[st]=0;T.ins(node(st,0));

        while(T.tot) {

            int u=T.pop();

            for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])

                if(dis[v]>dis[u]+val[p]) {

                    dis[v]=dis[u]+val[p];

                    T.ins(node(v,dis[v]));

                }

        }

    }

 

    void calc(int st) {

        cnt[st]=1;list[0]=st;h=0,t=1;

        while(h!=t) {

            int u=list[h++];

            for(int p=now[u],v=son[p];p;p=pre[p],v=son[p]) {

                cnt[v]+=cnt[u];

                if(--deg[v]==0)list[t++]=v;

            }

        }

    }

}G1,G2;

 

int main() {

    n=read(),m=read();

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

        a[i]=read(),b[i]=read(),c[i]=read();

        G1.add(a[i],b[i],c[i]);G2.add(b[i],a[i],c[i]);

    }G1.dij(1),G2.dij(2);

    G1.clear(),G2.clear();

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

        if(G1.dis[a[i]]+G2.dis[b[i]]+c[i]==G1.dis[2]) {

            bo[i]=1;

            G1.add(a[i],b[i],c[i]),G2.add(b[i],a[i],c[i]);

        }

    G1.calc(1),G2.calc(2);

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

        if(bo[i]) {

            if(G1.cnt[a[i]]*G2.cnt[b[i]]==G1.cnt[2])puts("SAD");

            else puts("SOSO");

        }

        else {

            if(G1.dis[b[i]]+c[i]+G2.dis[a[i]]<G1.dis[2])puts("HAPPY");

            else puts("SOSO");

        }

         

    }

    return 0;

}