Problem:
Problem F
  Pizza Delivery
Alyssa is a college student, living in New Tsukuba City. All the streets in the city are one-way. A new social experiment starting tomorrow is on alternative traffic regulation reversing the one-way directions of street sections. Reversals will be on one single street section between two adjacent intersections for each day; the directions of all the other sections will not change, and the reversal will be canceled on the next day.
Alyssa orders a piece of pizza everyday from the same pizzeria. The pizza is delivered along the shortest route from the intersection with the pizzeria to the intersection with Alyssa's house.
Altering the traffic regulation may change the shortest route. Please tell Alyssa how the social experiment will affect the pizza delivery route.
Input
The input consists of a single test case in the following format.
$n$ $m$
$a_1$ $b_1$ $c_1$
...
$a_m$ $b_m$ $c_m$
The first line contains two integers, $n$, the number of intersections, and $m$, the number of street sections in New Tsukuba City ($2 \leq n \leq 100 000, 1 \leq m \leq 100 000$). The intersections are numbered $1$ through $n$ and the street sections are numbered $1$ through $m$.
The following $m$ lines contain the information about the street sections, each with three integers $a_i$, $b_i$, and $c_i$ ($1 \leq a_i  n, 1 \leq b_i \leq n, a_i \ne b_i, 1 \leq c_i \leq 100 000$). They mean that the street section numbered $i$ connects two intersections with the one-way direction from $a_i$ to $b_i$, which will be reversed on the $i$-th day. The street section has the length of $c_i$. Note that there may be more than one street section connecting the same pair of intersections.
The pizzeria is on the intersection 1 and Alyssa's house is on the intersection 2. It is guaranteed that at least one route exists from the pizzeria to Alyssa's before the social experiment starts.
Output
The output should contain $m$ lines. The $i$-th line should be
HAPPY
if the shortest route on the $i$-th day will become shorter,
SOSO
if the length of the shortest route on the $i$-th day will not change, and
SAD
if the shortest route on the $i$-th day will be longer or if there will be no route from the pizzeria to Alyssa's house.
Alyssa doesn't mind whether the delivery bike can go back to the pizzeria or not.
Sample Input 1
4 5
1 3 5
3 4 6
4 2 7
2 1 18
2 3 12
Sample Output 1
SAD
SAD
SAD
SOSO
HAPPY
Sample Input 2
7 5
1 3 2
1 6 3
4 2 4
6 2 5
7 5 6
Sample Output 2
SOSO
SAD
SOSO
SAD
SOSO
Sample Input 3
10 14
1 7 9
1 8 3
2 8 4
2 6 11
3 7 8
3 4 4
3 2 1
3 2 7
4 8 4
5 6 11
5 8 12
6 10 6
7 10 8
8 3 6
Sample Output 3
SOSO
SAD
HAPPY
SOSO
SOSO
SOSO
SAD
SOSO
SOSO
SOSO
SOSO
SOSO
SOSO
SAD

Submitted solutions:

code_snippet: #include "bits/stdc++.h"
using namespace std;
#define FOR(i,s,t) for(int (i) = (s); (i)< (t); (i)++)
#define FORR(i,s,t) for(int (i) = (s); (i) > (t); (i)--)
#define debug(x) cout<<#x<<": "<<x<<endl;

typedef long long LL;
typedef vector<LL> VL;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<VL> VVL;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int INF = 1e9;
const ll LINF = 1e18;

struct edge {
	int u;
	int v;
	int cost;
	edge() {}
	edge(int u, int v, int cost) :u(u), v(v), cost(cost) {}
};

class Bridge {
public:
	set<pair<pii,int>> se;
	vector<vector<edge>> G;
	vector<int> ord, low;
	vector<pii> bridges;
	int k;
	Bridge(int N) :k(0) {
		G.resize(N); ord.resize(N, -1); low.resize(N, -1);
	}
	void clear() { G.clear(); ord.clear(); low.clear(); }
	void add_edge(int s, int t,int c) {
		G[s].emplace_back(edge(s,t,c)); G[t].emplace_back(edge(t,s,c));
	}
	bool is_bridge(int u, int v) const {
		if (ord[u] > ord[v]) swap(u, v);
		return ord[u] < low[v];
	}

	void dfs(int u,int rev = -1){
		ord[u] = low[u] = k;
		k++;
		for(auto e:G[u]){
			if (e.v == rev) continue;
			if (ord[e.v] < 0) {
				dfs(e.v, u);
				low[u] = min(low[u], low[e.v]);
			}
			else {
				low[u] = min(low[u], ord[e.v]);
			}
			if (is_bridge(u, e.v)) {
				int s = u, t = e.v;
				if (s > t) swap(s, t);
				bridges.push_back({ s,t });
				se.insert({ { s,t },e.cost }); se.insert({ { t,s },e.cost });

			}
		}
	}

	void solve() {
		dfs(0);
		sort(bridges.begin(), bridges.end());
	}

	bool check(int u,int v,int c) {
		return se.find({ { u,v },c }) != se.end();
//		return !(low[v] == -1 || low[u] == -1 || ord[v] == -1 || ord[u] == -1);
	}
};


vector<ll> dd(int s,int n,vector<vector<edge>>&G) {
	priority_queue<pll, vector<pll>, greater<pll>> q;
	vector<ll> d(n, LINF);
	q.push({ 0,s }); d[s] = 0;
	while (!q.empty()) {
		auto p = q.top(); q.pop();
		ll now = p.second;
		ll dist = p.first;
		if (d[now] < dist) continue;
		for (auto e : G[now]) {
			if (d[e.v] > d[e.u] + e.cost) {
				d[e.v] = d[e.u] + e.cost;
				q.push({ d[e.v],e.v });
			}
		}
	}
	return d;
}
int main() {
	cin.tie(0); ios::sync_with_stdio(false);
	int n, m; cin >> n >> m;
	vector<vector<edge>> G(n);
	vector<vector<edge>> rG(n);
	Bridge bribri(n);
	vector<edge> Event(m);
	for (int i = 0; i < m;i++) {
		int a, b, c; cin >> a >> b >> c;
		a--; b--;
		G[a].push_back(edge(a, b, c));
		rG[b].push_back(edge(b, a, c));
		Event[i] = edge(a, b, c);
	}

	vector<ll> d = dd(0,n, G);
	vector<ll> d2 = dd(1,n,rG);

	ll D = d[1]; //debug(D);
	for (int i = 0; i < n;i++) {
		for (auto e : G[i]) {
			if (d[e.u] + e.cost + d2[e.v] == D) {
				bribri.add_edge(e.u, e.v, e.cost);
			}
		}
	}
	bribri.solve();

	//for (auto bbb : bribri.bridges) {
	//	cout << bbb.first << " " << bbb.second << endl;
	//}

	vector<int> ans(m);
	for (int kassa = 0; kassa < m; kassa++) {
		auto e = Event[kassa];

		int kassa_is_bri = 0;

		//cout << " unko buri =========" << endl;

		//cout << e.v+1 << " " << e.u+1 << endl;
		//debug(d[e.v]);
		//debug(d[1] - d[e.u]);
		//debug(d[e.v] + e.cost + d2[e.u]);
		if (d[e.v] + e.cost + d2[e.u] < D) {
			ans[kassa] = 0;
			kassa_is_bri = 1;
			continue;
		}

		if (bribri.check(e.u, e.v,e.cost)) {
			if (kassa_is_bri == 1) {
		//		assert(0);
			}
			if (bribri.is_bridge(e.u, e.v)) {
				ans[kassa] = 2;
			}
			else {
				ans[kassa] = 1;
			}
		}
		else {
			ans[kassa] = 1;
		}
	}
	string unko[3] = { "HAPPY","SOSO","SAD" };
	for (auto aho : ans) {
		cout << unko[aho] << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 47408
final_rank: 12

code_snippet: #include<bits/stdc++.h>
using namespace std;

#define FOR(i,a,b) for(int i = (a); i < (b); i++)
#define RFOR(i,b,a) for(int i = (b) - 1; i >= (a); i--)
#define ITER(it,a) for(__typeof(a.begin()) it = a.begin(); it != a.end(); it++)
#define FILL(a,value) memset(a,value,sizeof(a))

#define SZ(a) (int)a.size()
#define ALL(a) a.begin(),a.end()
#define PB push_back
#define MP make_pair

typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;

const int INF = 1000 * 1000 * 1000 + 7;
const LL LINF = INF * (LL)INF;
const double PI = acos(-1.0);

const int MAX = 500500;
const int LEN = 20;

vector<PII> g[MAX];
vector<PII> gr[MAX];
VI I[MAX];

VI G[MAX];

LL D[2][MAX];

set<pair<LL, int> > S;

bool U[MAX];
int UP[MAX][LEN];
int H[MAX];

int n, m;

LL d;

int RES[MAX];

void dijk(vector<PII>* g, LL* D, int s)
{
	FOR (i, 0, n)
	{
		D[i] = LINF;
	}
	
	S.clear();
	
	D[s] = 0;
	S.insert(MP(D[s], s));
	
	while(SZ(S))
	{
		int x = S.begin()->second;
		S.erase(S.begin());
		
		FOR (i, 0, SZ(g[x]))
		{
			int to = g[x][i].first;
			int c = g[x][i].second;
			
			if (D[to] > D[x] + c)
			{
				S.erase(MP(D[to], to));
				D[to] = D[x] + c;
				S.insert(MP(D[to], to));
			}
		}
	}
}

int lca(int x, int y)
{
	RFOR(i, LEN, 0)
	{
		if (H[UP[x][i]] > H[y]) x = UP[x][i];
		if (H[UP[y][i]] > H[x]) y = UP[y][i];
	}
	
	if (H[y] > H[x]) y = UP[y][0];
	if (H[x] > H[y]) x = UP[x][0];
	
	RFOR(i, LEN, 0)
	{
		if (UP[x][i] != UP[y][i])
		{
			x = UP[x][i];
			y = UP[y][i];
		}
	}
	
	return UP[x][0];
}

void add(int x, int p)
{
//	cout<<"% "<<x<<' '<<p<<endl;
	if (p == -1)
	{
		H[x] = 0;
		
		FOR (i, 0, LEN)
		{
			UP[x][i] = x;
		}
		
		return;
	}
	
	H[x] = H[p] + 1;
	UP[x][0] = p;
	FOR (i, 1, LEN)
	{
		UP[x][i] = UP[UP[x][i-1]][i-1];
	}
}

void dfs(int x)
{
	if (U[x]) return;
	U[x] = true;
	FOR (i, 0, SZ(G[x]))
	{
		int to = G[x][i];
		dfs(to);
	}
	
	int v = -1;
	FOR (i, 0, SZ(G[x]))
	{
		int to = G[x][i];
		
		if (v == -1) v = to;
		else v = lca(v, to);
	}
	
	add(x, v);
}

void build()
{
	FOR (i, 0, n)
	{
		FOR (j, 0, SZ(g[i]))
		{
			int to = g[i][j].first;
			int c = g[i][j].second;
			
			if (D[0][to] == D[0][i] + c)
			{
				int ind = I[i][j];
				
				G[to].PB(n + ind);
				G[n + ind].PB(i);
				
//				cout<<"@@ "<<i<<' '<<n+ind<<endl;
//				cout<<"@@ "<<n + ind<<' '<<to<<endl;
			}
		}
	}
	
	FILL(U, false);
	
	FOR (i, 0, n+m)
	{
		dfs(i);
	}
}

int check(int x, int y, int c, int ind)
{
	LL dist = D[0][y] + c + D[1][x];
//	cout<<"!! "<<x<<' '<<y<<' '<<c<<' '<<ind<<": "<<dist<<' '<<d<<endl;
	if (dist < d)
	{
		RES[ind] = 0;
		return 0;
	}
	
//	dist = D[0][x] + c + D[1][y];
//	if (dist == d)
//	{
//		int par = UP[y][0];
//		
//		cout<<"!! "<<x<<' '<<y<<' '<<ind<<": "<<par<<' '<<ind + n<<endl;
//		
//		if (par == ind + n)
//		{
//			RES[ind] = 2;
//			return 2;
//		}
//	}
	
	RES[ind] = 1;
	return 1;
}

string T[3] = {"HAPPY", "SOSO", "SAD"};

int main()
{
//	freopen("in.txt","r", stdin);
	//ios::sync_with_stdio(false);cin.tie(0);
	
	scanf("%d%d", &n, &m);
	
	FOR (i, 0, m)
	{
		int x, y, c;
		scanf("%d%d%d", &x, &y, &c);
		x--;
		y--;
		
		g[x].PB(MP(y, c));
		gr[y].PB(MP(x, c));
		
		I[x].PB(i);
	}
	
	FILL(RES, -1);
	
	dijk(g, D[0], 0);
	dijk(gr, D[1], 1);
	
//	FOR (i, 0, n)
//	{
//		cout<<D[0][i]<<' ';
//	}
//	cout<<endl;
//	
//	FOR (i, 0, n)
//	{
//		cout<<D[1][i]<<' ';
//	}
//	cout<<endl;

	FILL(UP, -1);
	
	build();
	
//	FOR (i, 0, n+m)
//	{
//		cout<<i<<": "<<UP[i][0]<<endl;
//	}
	
	::d = D[0][1];
	
//	cout<<check(0, 2, 5, 0)<<endl;
//	return 0;
	
	FOR (i, 0, n)
	{
		FOR (j, 0, SZ(g[i]))
		{
			int to = g[i][j].first;
			int c = g[i][j].second;
			
			check(i, to, c, I[i][j]);
		}
	}
	
	int x = 1;
	while(true)
	{
		if (UP[x][0] == x) break;
		x = UP[x][0];
		
		if (x >= n)
		{
			RES[x - n] = 2;
		}
	}
	
	FOR (i, 0, m)
	{
		printf("%s\n", T[RES[i]].c_str());
	}
}
accuracy: 0.8297872340425532
time_ms: 120
memory_kb: 119452
final_rank: 14

code_snippet: #include <iostream>
#include <iomanip>
#include <cassert>
#include <vector>
#include <algorithm>
#include <utility>
#include <numeric>
#include <tuple>
// #include "Src/Number/IntegerDivision.hpp"
// #include "Src/Utility/BinarySearch.hpp"
// #include "Src/Sequence/CompressedSequence.hpp"
// #include "Src/Sequence/RunLengthEncoding.hpp"
// #include "Src/Algebra/Group/AdditiveGroup.hpp"
// #include "Src/DataStructure/FenwickTree/FenwickTree.hpp"
// using namespace zawa;
// #include "atcoder/modint"
// using mint = atcoder::modint998244353;
#include <queue>
int N, M;
std::tuple<int, int, int> E[100010];
std::vector<std::pair<int, int>> g[100010], rev[100010];
int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    std::cin >> N >> M;
    for (int i = 0 ; i < M ; i++) {
        int A, B, C;
        std::cin >> A >> B >> C;
        A--; B--;
        g[A].push_back({B, C});
        rev[B].push_back({A, C});
        E[i] = {C, A, B};
    }
    std::vector<long long> dist(N, (long long)1e18);
    {
        using qt = std::pair<long long, int>;
        std::priority_queue<qt, std::vector<qt>, std::greater<qt>> que;
        dist[0] = 0;
        que.push({dist[0], 0});
        while (que.size()) {
            auto [d, v] = que.top();
            que.pop();
            if (dist[v] < d) continue;
            for (auto [x, w] : g[v]) if (dist[x] > d + w) {
                dist[x] = d + w;
                que.push({dist[x], x});
            }
        }
    }
    // for (auto d : dist) std::cout <<d  << ' ';
    // std::cout << std::endl;
    std::vector<std::vector<std::pair<int, int>>> dag(N), gad(N);
    std::vector<bool> indag(M);
    for (int i = 0 ; i < M ; i++) {
        auto [c, u, v] = E[i];
        if (dist[u] + c == dist[v]) {
            // std::cout << c << ' ' << u +1 << ' ' << v+ 1 << std::endl;
            dag[u].push_back({v, i});
            gad[v].push_back({u, i});
            indag[i] = true;
        }
    }
    std::vector<bool> reach(N);
    {
        std::queue<int> que;
        que.push(1);
        reach[1] = true;
        while (que.size()) {
            int v = que.front();
            que.pop();
            for (auto x : gad[v]) if (!reach[x.first]) {
                reach[x.first] = true;
                que.push(x.first);
            }
        }
    }
    // assert(reach[0]);
    std::vector<int> d(N, -1);
    {
        std::queue<int> que;
        que.push(0);
        d[0] = 0;
        while (que.size()) {
            int v = que.front();
            que.pop();
            for (auto x : dag[v]) if (reach[x.first] and d[x.first] == -1) {
                d[x.first] = d[v] + 1;
                que.push(x.first);
            }
        }
    }
    for (int i = 0 ; i < M ; i++) if (indag[i]) {
        auto [c, u, v] = E[i];
        if (!reach[u] or !reach[v]) indag[i] = false;
    }
    std::vector<long long> dist2(N, (long long)1e18);
    {
        using qt = std::pair<long long, int>;
        std::priority_queue<qt, std::vector<qt>, std::greater<qt>> que;
        dist2[1] = 0;
        que.push({dist2[1], 1});
        while (que.size()) {
            auto [d, v] = que.top();
            que.pop();
            if (dist2[v] < d) continue;
            for (auto [x, w] : rev[v]) if (dist2[x] > d + w) {
                dist2[x] = d + w;
                que.push({dist2[x], x});
            }
        }
    }
    std::vector<std::vector<std::pair<int, int>>> both(N);
    for (int i = 0 ; i < M ; i++) if (indag[i]) {
        auto [c, u, v] = E[i];
        both[u].push_back({v, i});
        both[v].push_back({u, i});
    }
    const int INVALID = (int)1e9;
    std::vector<int> in(N, INVALID), low(N);
    std::vector<bool> bridge(M);
    auto dfs = [&](auto dfs, int v, int p, int& t) -> void {
        low[v] = in[v] = t++;
        int deg = 0;
        for (auto [x, i] : both[v]) {
            if (in[x] == INVALID) {
                deg++;
                dfs(dfs, x, v, t);
                low[v] = std::min(low[v], low[x]);
                if (low[x] > in[v]) {
                    bridge[i] = true;
                }
            }
            else if (x != p) {
                low[v] = std::min(low[v], in[x]);
            }
        }
    };
    int t = 0;
    for (int i = 0 ; i < N ; i++) if (in[i] == INVALID) {
        dfs(dfs, i, INVALID, t);
    }
    for (int i = 0 ; i < M ; i++) {
        auto [c, u, v] = E[i];
        if (indag[i]) {
            // assert(d[u] + 1 == d[v]);
            if (bridge[i]) std::cout << "SAD\n";
            else std::cout << "SOSO\n";
        }
        else {
            // std::cout << c << ' ' << u + 1 << ' ' << v + 1 << std::endl;
            if (dist[v] + c + dist2[u] < dist[1]) std::cout << "HAPPY\n";
            else std::cout << "SOSO\n";
        }
    }
}
accuracy: 1
time_ms: 70
memory_kb: 50280
final_rank: 4

code_snippet: #include <iostream>
#include <iomanip>
#include <cassert>
#include <vector>
#include <algorithm>
#include <utility>
#include <numeric>
#include <map>
#include <tuple>
// #include "Src/Number/IntegerDivision.hpp"
// #include "Src/Utility/BinarySearch.hpp"
// #include "Src/Sequence/CompressedSequence.hpp"
// #include "Src/Sequence/RunLengthEncoding.hpp"
// #include "Src/Algebra/Group/AdditiveGroup.hpp"
// #include "Src/DataStructure/FenwickTree/FenwickTree.hpp"
// using namespace zawa;
// #include "atcoder/modint"
// using mint = atcoder::modint998244353;
#include <queue>
int N, M;
std::tuple<int, int, int> E[100010];
std::vector<std::pair<int, int>> g[100010], rev[100010];
int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    std::cin >> N >> M;
    for (int i = 0 ; i < M ; i++) {
        int A, B, C;
        std::cin >> A >> B >> C;
        A--; B--;
        g[A].push_back({B, C});
        rev[B].push_back({A, C});
        E[i] = {C, A, B};
    }
    std::vector<long long> dist(N, (long long)1e18);
    {
        using qt = std::pair<long long, int>;
        std::priority_queue<qt, std::vector<qt>, std::greater<qt>> que;
        dist[0] = 0;
        que.push({dist[0], 0});
        while (que.size()) {
            auto [d, v] = que.top();
            que.pop();
            if (dist[v] < d) continue;
            for (auto [x, w] : g[v]) if (dist[x] > d + w) {
                dist[x] = d + w;
                que.push({dist[x], x});
            }
        }
    }
    // for (auto d : dist) std::cout <<d  << ' ';
    // std::cout << std::endl;
    std::vector<std::vector<std::pair<int, int>>> dag(N), gad(N);
    std::vector<bool> indag(M);
    for (int i = 0 ; i < M ; i++) {
        auto [c, u, v] = E[i];
        if (dist[u] + c == dist[v]) {
            // std::cout << c << ' ' << u +1 << ' ' << v+ 1 << std::endl;
            dag[u].push_back({v, i});
            gad[v].push_back({u, i});
            indag[i] = true;
        }
    }
    std::vector<bool> reach(N);
    {
        std::queue<int> que;
        que.push(1);
        reach[1] = true;
        while (que.size()) {
            int v = que.front();
            que.pop();
            for (auto x : gad[v]) if (!reach[x.first]) {
                reach[x.first] = true;
                que.push(x.first);
            }
        }
    }
    // assert(reach[0]);
    std::vector<int> d(N, -1);
    {
        std::queue<int> que;
        que.push(0);
        d[0] = 0;
        while (que.size()) {
            int v = que.front();
            que.pop();
            for (auto x : dag[v]) if (reach[x.first] and d[x.first] == -1) {
                d[x.first] = d[v] + 1;
                que.push(x.first);
            }
        }
    }
    for (int i = 0 ; i < M ; i++) if (indag[i]) {
        auto [c, u, v] = E[i];
        if (!reach[u] or !reach[v]) indag[i] = false;
    }
    std::vector<long long> dist2(N, (long long)1e18);
    {
        using qt = std::pair<long long, int>;
        std::priority_queue<qt, std::vector<qt>, std::greater<qt>> que;
        dist2[1] = 0;
        que.push({dist2[1], 1});
        while (que.size()) {
            auto [d, v] = que.top();
            que.pop();
            if (dist2[v] < d) continue;
            for (auto [x, w] : rev[v]) if (dist2[x] > d + w) {
                dist2[x] = d + w;
                que.push({dist2[x], x});
            }
        }
    }
    std::vector<std::vector<std::pair<int, int>>> both(N);
    for (int i = 0 ; i < M ; i++) if (indag[i]) {
        auto [c, u, v] = E[i];
        both[u].push_back({v, i});
        both[v].push_back({u, i});
    }
    const int INVALID = (int)1e9;
    std::vector<int> in(N, INVALID), low(N);
    std::vector<bool> bridge(M);
    auto dfs = [&](auto dfs, int v, int p, int& t) -> void {
        low[v] = in[v] = t++;
        int deg = 0;
        for (auto [x, i] : both[v]) {
            if (in[x] == INVALID) {
                deg++;
                dfs(dfs, x, v, t);
                low[v] = std::min(low[v], low[x]);
                if (low[x] > in[v]) {
                    bridge[i] = true;
                }
            }
            else if (x != p) {
                low[v] = std::min(low[v], in[x]);
            }
        }
    };
    int t = 0;
    for (int i = 0 ; i < N ; i++) if (in[i] == INVALID) {
        dfs(dfs, i, INVALID, t);
    }
    std::map<std::tuple<int, int, int>, int> map;
    for (int i = 0 ; i < M ; i++) map[E[i]]++;
    for (int i = 0 ; i < M ; i++) {
        auto [c, u, v] = E[i];
        if (indag[i]) {
            if (map[E[i]] >= 2) {
                std::cout << "SOSO\n";
            }
            // assert(d[u] + 1 == d[v]);
            if (bridge[i]) std::cout << "SAD\n";
            else std::cout << "SOSO\n";
        }
        else {
            // std::cout << c << ' ' << u + 1 << ' ' << v + 1 << std::endl;
            if (dist[v] + c + dist2[u] < dist[1]) std::cout << "HAPPY\n";
            else std::cout << "SOSO\n";
        }
    }
}
accuracy: 0.8297872340425532
time_ms: 100
memory_kb: 56556
final_rank: 13

code_snippet: #include <iostream>
#include <iomanip>
#include <cassert>
#include <vector>
#include <algorithm>
#include <utility>
#include <numeric>
#include <map>
#include <tuple>
// #include "Src/Number/IntegerDivision.hpp"
// #include "Src/Utility/BinarySearch.hpp"
// #include "Src/Sequence/CompressedSequence.hpp"
// #include "Src/Sequence/RunLengthEncoding.hpp"
// #include "Src/Algebra/Group/AdditiveGroup.hpp"
// #include "Src/DataStructure/FenwickTree/FenwickTree.hpp"
// using namespace zawa;
// #include "atcoder/modint"
// using mint = atcoder::modint998244353;
#include <queue>
int N, M;
std::tuple<int, int, int> E[100010];
std::vector<std::pair<int, int>> g[100010], rev[100010];
int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    std::cin >> N >> M;
    for (int i = 0 ; i < M ; i++) {
        int A, B, C;
        std::cin >> A >> B >> C;
        A--; B--;
        g[A].push_back({B, C});
        rev[B].push_back({A, C});
        E[i] = {C, A, B};
    }
    std::vector<long long> dist(N, (long long)1e18);
    {
        using qt = std::pair<long long, int>;
        std::priority_queue<qt, std::vector<qt>, std::greater<qt>> que;
        dist[0] = 0;
        que.push({dist[0], 0});
        while (que.size()) {
            auto [d, v] = que.top();
            que.pop();
            if (dist[v] < d) continue;
            for (auto [x, w] : g[v]) if (dist[x] > d + w) {
                dist[x] = d + w;
                que.push({dist[x], x});
            }
        }
    }
    // for (auto d : dist) std::cout <<d  << ' ';
    // std::cout << std::endl;
    std::vector<std::vector<std::pair<int, int>>> dag(N), gad(N);
    std::vector<bool> indag(M);
    for (int i = 0 ; i < M ; i++) {
        auto [c, u, v] = E[i];
        if (dist[u] + c == dist[v]) {
            // std::cout << c << ' ' << u +1 << ' ' << v+ 1 << std::endl;
            dag[u].push_back({v, i});
            gad[v].push_back({u, i});
            indag[i] = true;
        }
    }
    std::vector<bool> reach(N);
    {
        std::queue<int> que;
        que.push(1);
        reach[1] = true;
        while (que.size()) {
            int v = que.front();
            que.pop();
            for (auto x : gad[v]) if (!reach[x.first]) {
                reach[x.first] = true;
                que.push(x.first);
            }
        }
    }
    // assert(reach[0]);
    std::vector<int> d(N, -1);
    {
        std::queue<int> que;
        que.push(0);
        d[0] = 0;
        while (que.size()) {
            int v = que.front();
            que.pop();
            for (auto x : dag[v]) if (reach[x.first] and d[x.first] == -1) {
                d[x.first] = d[v] + 1;
                que.push(x.first);
            }
        }
    }
    for (int i = 0 ; i < M ; i++) if (indag[i]) {
        auto [c, u, v] = E[i];
        if (!reach[u] or !reach[v]) indag[i] = false;
    }
    std::vector<long long> dist2(N, (long long)1e18);
    {
        using qt = std::pair<long long, int>;
        std::priority_queue<qt, std::vector<qt>, std::greater<qt>> que;
        dist2[1] = 0;
        que.push({dist2[1], 1});
        while (que.size()) {
            auto [d, v] = que.top();
            que.pop();
            if (dist2[v] < d) continue;
            for (auto [x, w] : rev[v]) if (dist2[x] > d + w) {
                dist2[x] = d + w;
                que.push({dist2[x], x});
            }
        }
    }
    std::vector<std::vector<std::pair<int, int>>> both(N);
    for (int i = 0 ; i < M ; i++) if (indag[i]) {
        auto [c, u, v] = E[i];
        both[u].push_back({v, i});
        both[v].push_back({u, i});
    }
    const int INVALID = (int)1e9;
    std::vector<int> in(N, INVALID), low(N);
    std::vector<bool> bridge(M);
    auto dfs = [&](auto dfs, int v, int p, int& t) -> void {
        low[v] = in[v] = t++;
        int deg = 0;
        for (auto [x, i] : both[v]) {
            if (in[x] == INVALID) {
                deg++;
                dfs(dfs, x, v, t);
                low[v] = std::min(low[v], low[x]);
                if (low[x] > in[v]) {
                    bridge[i] = true;
                }
            }
            else if (x != p) {
                low[v] = std::min(low[v], in[x]);
            }
        }
    };
    int t = 0;
    for (int i = 0 ; i < N ; i++) if (in[i] == INVALID) {
        dfs(dfs, i, INVALID, t);
    }
    std::map<std::tuple<int, int, int>, int> map;
    for (int i = 0 ; i < M ; i++) map[E[i]]++;
    for (int i = 0 ; i < M ; i++) {
        auto [c, u, v] = E[i];
        if (map[E[i]] >= 2) {
            std::cout << "SOSO\n";
        }
        else if (indag[i]) {
            // assert(d[u] + 1 == d[v]);
            if (bridge[i]) std::cout << "SAD\n";
            else std::cout << "SOSO\n";
        }
        else {
            // std::cout << c << ' ' << u + 1 << ' ' << v + 1 << std::endl;
            if (dist[v] + c + dist2[u] < dist[1]) std::cout << "HAPPY\n";
            else std::cout << "SOSO\n";
        }
    }
}
accuracy: 0.44680851063829785
time_ms: 100
memory_kb: 56508
final_rank: 15

code_snippet: #include <iostream>
#include <iomanip>
#include <cassert>
#include <vector>
#include <algorithm>
#include <utility>
#include <numeric>
#include <map>
#include <tuple>
// #include "Src/Number/IntegerDivision.hpp"
// #include "Src/Utility/BinarySearch.hpp"
// #include "Src/Sequence/CompressedSequence.hpp"
// #include "Src/Sequence/RunLengthEncoding.hpp"
// #include "Src/Algebra/Group/AdditiveGroup.hpp"
// #include "Src/DataStructure/FenwickTree/FenwickTree.hpp"
// using namespace zawa;
// #include "atcoder/modint"
// using mint = atcoder::modint998244353;
#include <queue>
int N, M;
std::tuple<int, int, int> E[100010];
std::vector<std::pair<int, int>> g[100010], rev[100010];
int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    std::cin >> N >> M;
    for (int i = 0 ; i < M ; i++) {
        int A, B, C;
        std::cin >> A >> B >> C;
        A--; B--;
        g[A].push_back({B, C});
        rev[B].push_back({A, C});
        E[i] = {C, A, B};
    }
    std::vector<long long> dist(N, (long long)1e18);
    {
        using qt = std::pair<long long, int>;
        std::priority_queue<qt, std::vector<qt>, std::greater<qt>> que;
        dist[0] = 0;
        que.push({dist[0], 0});
        while (que.size()) {
            auto [d, v] = que.top();
            que.pop();
            if (dist[v] < d) continue;
            for (auto [x, w] : g[v]) if (dist[x] > d + w) {
                dist[x] = d + w;
                que.push({dist[x], x});
            }
        }
    }
    // for (auto d : dist) std::cout <<d  << ' ';
    // std::cout << std::endl;
    std::vector<std::vector<std::pair<int, int>>> dag(N), gad(N);
    std::vector<bool> indag(M);
    for (int i = 0 ; i < M ; i++) {
        auto [c, u, v] = E[i];
        if (dist[u] + c == dist[v]) {
            // std::cout << c << ' ' << u +1 << ' ' << v+ 1 << std::endl;
            dag[u].push_back({v, i});
            gad[v].push_back({u, i});
            indag[i] = true;
        }
    }
    std::vector<bool> reach(N);
    {
        std::queue<int> que;
        que.push(1);
        reach[1] = true;
        while (que.size()) {
            int v = que.front();
            que.pop();
            for (auto x : gad[v]) if (!reach[x.first]) {
                reach[x.first] = true;
                que.push(x.first);
            }
        }
    }
    // assert(reach[0]);
    std::vector<int> d(N, -1);
    {
        std::queue<int> que;
        que.push(0);
        d[0] = 0;
        while (que.size()) {
            int v = que.front();
            que.pop();
            for (auto x : dag[v]) if (reach[x.first] and d[x.first] == -1) {
                d[x.first] = d[v] + 1;
                que.push(x.first);
            }
        }
    }
    for (int i = 0 ; i < M ; i++) if (indag[i]) {
        auto [c, u, v] = E[i];
        if (!reach[u] or !reach[v]) indag[i] = false;
    }
    std::vector<long long> dist2(N, (long long)1e18);
    {
        using qt = std::pair<long long, int>;
        std::priority_queue<qt, std::vector<qt>, std::greater<qt>> que;
        dist2[1] = 0;
        que.push({dist2[1], 1});
        while (que.size()) {
            auto [d, v] = que.top();
            que.pop();
            if (dist2[v] < d) continue;
            for (auto [x, w] : rev[v]) if (dist2[x] > d + w) {
                dist2[x] = d + w;
                que.push({dist2[x], x});
            }
        }
    }
    std::vector<std::vector<std::pair<int, int>>> both(N);
    for (int i = 0 ; i < M ; i++) if (indag[i]) {
        auto [c, u, v] = E[i];
        both[u].push_back({v, i});
        both[v].push_back({u, i});
    }
    const int INVALID = (int)1e9;
    std::vector<int> in(N, INVALID), low(N);
    std::vector<bool> bridge(M);
    auto dfs = [&](auto dfs, int v, int p, int& t) -> void {
        low[v] = in[v] = t++;
        int deg = 0;
        for (auto [x, i] : both[v]) {
            if (in[x] == INVALID) {
                deg++;
                dfs(dfs, x, v, t);
                low[v] = std::min(low[v], low[x]);
                if (low[x] > in[v]) {
                    bridge[i] = true;
                }
            }
            else if (x != p) {
                low[v] = std::min(low[v], in[x]);
            }
        }
    };
    int t = 0;
    for (int i = 0 ; i < N ; i++) if (in[i] == INVALID) {
        dfs(dfs, i, INVALID, t);
    }
    std::map<std::tuple<int, int, int>, int> map;
    for (int i = 0 ; i < M ; i++) map[E[i]]++;
    for (int i = 0 ; i < M ; i++) {
        auto [c, u, v] = E[i];
        if (map[E[i]] >= 2) {
            std::cout << "SOSO\n";
        }
        else if (indag[i]) {
            assert(d[u] + 1 == d[v]);
            if (bridge[i]) std::cout << "SAD\n";
            else std::cout << "SOSO\n";
        }
        else {
            // std::cout << c << ' ' << u + 1 << ' ' << v + 1 << std::endl;
            if (dist[v] + c + dist2[u] < dist[1]) std::cout << "HAPPY\n";
            else std::cout << "SOSO\n";
        }
    }
}
accuracy: 0.0851063829787234
time_ms: 100
memory_kb: 56512
final_rank: 18

code_snippet: #include <iostream>
#include <iomanip>
#include <cassert>
#include <vector>
#include <algorithm>
#include <utility>
#include <numeric>
#include <map>
#include <tuple>
// #include "Src/Number/IntegerDivision.hpp"
// #include "Src/Utility/BinarySearch.hpp"
// #include "Src/Sequence/CompressedSequence.hpp"
// #include "Src/Sequence/RunLengthEncoding.hpp"
// #include "Src/Algebra/Group/AdditiveGroup.hpp"
// #include "Src/DataStructure/FenwickTree/FenwickTree.hpp"
// using namespace zawa;
// #include "atcoder/modint"
// using mint = atcoder::modint998244353;
#include <queue>
int N, M;
std::tuple<int, int, int> E[100010];
std::vector<std::pair<int, int>> g[100010], rev[100010];
int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    std::cin >> N >> M;
    for (int i = 0 ; i < M ; i++) {
        int A, B, C;
        std::cin >> A >> B >> C;
        A--; B--;
        g[A].push_back({B, C});
        rev[B].push_back({A, C});
        E[i] = {C, A, B};
    }
    std::vector<long long> dist(N, (long long)1e18);
    {
        using qt = std::pair<long long, int>;
        std::priority_queue<qt, std::vector<qt>, std::greater<qt>> que;
        dist[0] = 0;
        que.push({dist[0], 0});
        while (que.size()) {
            auto [d, v] = que.top();
            que.pop();
            if (dist[v] < d) continue;
            for (auto [x, w] : g[v]) if (dist[x] > d + w) {
                dist[x] = d + w;
                que.push({dist[x], x});
            }
        }
    }
    // for (auto d : dist) std::cout <<d  << ' ';
    // std::cout << std::endl;
    std::vector<std::vector<std::pair<int, int>>> dag(N), gad(N);
    std::vector<bool> indag(M);
    for (int i = 0 ; i < M ; i++) {
        auto [c, u, v] = E[i];
        if (dist[u] + c == dist[v]) {
            // std::cout << c << ' ' << u +1 << ' ' << v+ 1 << std::endl;
            dag[u].push_back({v, i});
            gad[v].push_back({u, i});
            indag[i] = true;
        }
    }
    std::vector<bool> reach(N);
    {
        std::queue<int> que;
        que.push(1);
        reach[1] = true;
        while (que.size()) {
            int v = que.front();
            que.pop();
            for (auto x : gad[v]) if (!reach[x.first]) {
                reach[x.first] = true;
                que.push(x.first);
            }
        }
    }
    assert(reach[0]);
    std::vector<int> d(N, -1);
    {
        std::queue<int> que;
        que.push(0);
        d[0] = 0;
        while (que.size()) {
            int v = que.front();
            que.pop();
            for (auto x : dag[v]) if (reach[x.first] and d[x.first] == -1) {
                d[x.first] = d[v] + 1;
                que.push(x.first);
            }
        }
    }
    for (int i = 0 ; i < M ; i++) if (indag[i]) {
        auto [c, u, v] = E[i];
        if (!reach[u] or !reach[v]) indag[i] = false;
    }
    std::vector<long long> dist2(N, (long long)1e18);
    {
        using qt = std::pair<long long, int>;
        std::priority_queue<qt, std::vector<qt>, std::greater<qt>> que;
        dist2[1] = 0;
        que.push({dist2[1], 1});
        while (que.size()) {
            auto [d, v] = que.top();
            que.pop();
            if (dist2[v] < d) continue;
            for (auto [x, w] : rev[v]) if (dist2[x] > d + w) {
                dist2[x] = d + w;
                que.push({dist2[x], x});
            }
        }
    }
    std::vector<std::vector<std::pair<int, int>>> both(N);
    for (int i = 0 ; i < M ; i++) if (indag[i]) {
        auto [c, u, v] = E[i];
        both[u].push_back({v, i});
        both[v].push_back({u, i});
    }
    const int INVALID = (int)1e9;
    std::vector<int> in(N, INVALID), low(N);
    std::vector<bool> bridge(M);
    auto dfs = [&](auto dfs, int v, int p, int& t) -> void {
        low[v] = in[v] = t++;
        int deg = 0;
        for (auto [x, i] : both[v]) {
            if (in[x] == INVALID) {
                deg++;
                dfs(dfs, x, v, t);
                low[v] = std::min(low[v], low[x]);
                if (low[x] > in[v]) {
                    bridge[i] = true;
                }
            }
            else if (x != p) {
                low[v] = std::min(low[v], in[x]);
            }
        }
    };
    int t = 0;
    for (int i = 0 ; i < N ; i++) if (in[i] == INVALID) {
        dfs(dfs, i, INVALID, t);
    }
    std::map<std::tuple<int, int, int>, int> map;
    for (int i = 0 ; i < M ; i++) map[E[i]]++;
    for (int i = 0 ; i < M ; i++) {
        auto [c, u, v] = E[i];
        if (map[E[i]] >= 2) {
            std::cout << "SOSO\n";
        }
        else if (indag[i]) {
            assert(d[u] + 1 == d[v]);
            if (bridge[i]) std::cout << "SAD\n";
            else std::cout << "SOSO\n";
        }
        else {
            // std::cout << c << ' ' << u + 1 << ' ' << v + 1 << std::endl;
            if (dist[v] + c + dist2[u] < dist[1]) std::cout << "HAPPY\n";
            else std::cout << "SOSO\n";
        }
    }
}
accuracy: 0.0851063829787234
time_ms: 100
memory_kb: 56512
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(ll i=0; i<ll(n); i++)
#define all(v) v.begin(), v.end()
template<class T> void chmin(T& l, const T& r){ if(r < l) l = r; }
template<class T> void chmax(T& l, const T& r){ if(l < r) l = r; }
const ll INF = 1ll << 60;

void testcase(){
    int N, M; cin >> N >> M;
    vector<int> A(M), B(M), C(M);
    vector<vector<pair<int,int>>> adj0(N), adj1(N);
    rep(i,M){
        int a,b,c; cin >> a >> b >> c; a--; b--;
        A[i] = a; B[i] = b; C[i] = c;
        adj0[a].push_back({ b,c });
        adj1[b].push_back({ a,c });
    }
    auto dist = [&](vector<vector<pair<int,int>>>& E, int s) -> vector<ll> {
        vector<ll> d(N,INF);
        d[s] = 0;
        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> que;
        que.push({ 0,s });
        while(que.size()){
            auto [x,u] = que.top(); que.pop();
            if(d[u] != x) continue;
            for(auto [v,c] : E[u]){
                if(d[v] <= d[u]+c) continue;
                d[v] = d[u]+c;
                que.push({d[u]+c,v});
            }
        }
        return d;
    };
    auto d0 = dist(adj0, 0);
    auto d1 = dist(adj1, 1);
    ll D = d0[1];
    vector<ll> term;
    rep(i,N) if(d0[i] + d1[i] == D) term.push_back(d0[i]);
    sort(all(term));
    vector<int> imos(term.size()+1);
    vector<int> ans(M, -1);
    rep(i,M){
        if(d0[B[i]] + d1[A[i]] + C[i] < D) ans[i] = 1;
        if(d0[B[i]] + d1[A[i]] + C[i] == D) ans[i] = 0;
        if(d0[A[i]] + d1[B[i]] + C[i] == D){
            int l = lower_bound(all(term), d0[A[i]]) - term.begin();
            int r = lower_bound(all(term), d0[B[i]]) - term.begin();
            imos[l] += 1;
            imos[r] -= 1;
        }
    }
    rep(i,imos.size()-1) imos[i+1] += imos[i];
    rep(i,M) if(ans[i] == -1){
        if(d0[A[i]] + d1[B[i]] + C[i] == D){
            int l = lower_bound(all(term), d0[A[i]]) - term.begin();
            int r = lower_bound(all(term), d0[B[i]]) - term.begin();
            if(imos[l] != 1) ans[i] = 0;
        } else {
            ans[i] = 0;
        }
    }
    rep(i,M){
        if(ans[i] == 1) cout << "HAPPY\n";
        else if(ans[i] == 0) cout << "SOSO\n";
        else cout << "SAD\n";
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    testcase();
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 18356
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define all(a) a.begin(),a.end()
#define reps(i, a, n) for (int i = (a); i < (int)(n); i++)
#define rep(i, n) reps(i, 0, n)
#define rreps(i, a, n) for (int i = (a); i > (int)(n); i--)
const long long mod = 1000000007;
const long long INF = 1e18;
ll myceil(ll a, ll b) {return (a+b-1)/b;}


#ifndef ATCODER_INTERNAL_TYPE_TRAITS_HPP
#define ATCODER_INTERNAL_TYPE_TRAITS_HPP 1

#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_INTERNAL_TYPE_TRAITS_HPP

#ifndef ATCODER_INTERNAL_MATH_HPP
#define ATCODER_INTERNAL_MATH_HPP 1

#include <utility>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m`
    explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned long long y = x * _m;
        return (unsigned int)(z - y + (z < y ? _m : 0));
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

// @param n `n < 2^32`
// @param m `1 <= m < 2^32`
// @return sum_{i=0}^{n-1} floor((ai + b) / m) (mod 2^64)
unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
    unsigned long long ans = 0;
    while (true) {
        if (a >= m) {
            ans += n * (n - 1) / 2 * (a / m);
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        unsigned long long y_max = a * n + b;
        if (y_max < m) break;
        // y_max < m * (n + 1)
        // floor(y_max / m) <= n
        n = (unsigned long long)(y_max / m);
        b = (unsigned long long)(y_max % m);
        std::swap(m, a);
    }
    return ans;
}

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_INTERNAL_MATH_HPP

#ifndef ATCODER_MODINT_HPP
#define ATCODER_MODINT_HPP 1

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_MODINT_HPP





using namespace atcoder;
using mint = modint998244353;



void solve() {
    ll n,m;
    cin >> n >> m;
    vector<vector<ll>> v(m,vector<ll> (3));
    vector<vector<pair<ll,ll>>> edge(n);
    vector<vector<pair<ll,ll>>> rev_edge(n);
    rep(i,m) {
        cin >> v[i][0] >> v[i][1] >> v[i][2];
        v[i][0]--;
        v[i][1]--;
        edge[v[i][0]].push_back({v[i][2],v[i][1]});
        rev_edge[v[i][1]].push_back({v[i][2],v[i][0]});
    }
    vector<pair<ll,mint>> f1(n,{INF,0}), fn(n,{INF,0});


    priority_queue<pair<ll,ll>,vector<pair<ll,ll>>,greater<pair<ll,ll>>> pq;

    pq.push({0,0});

    f1[0] = {0,1};

    while (!pq.empty()) {
        auto p = pq.top();
        pq.pop();
        if (f1[p.second].first != p.first) {
            continue;
        }
        for (auto x : edge[p.second]) {
            if (p.first+x.first < f1[x.second].first) {
                pq.push({p.first+x.first,x.second});
                f1[x.second].first = p.first+x.first; 
                f1[x.second].second = f1[p.second].second;
            }
            else if (p.first+x.first == f1[x.second].first) {
                f1[x.second].second += f1[p.second].second;
            }
        }
    }

    fn[1] = {0,1};
    pq.push({0,1});

    while (!pq.empty()) {
        auto p = pq.top();
        pq.pop();
        if (fn[p.second].first != p.first) {
            continue;
        }
        for (auto x : rev_edge[p.second]) {
            if (p.first+x.first < fn[x.second].first) {
                pq.push({p.first+x.first,x.second});
                fn[x.second].first = p.first+x.first; 
                fn[x.second].second = fn[p.second].second;        
            }
            else if(p.first+x.first == fn[x.second].first) {
                fn[x.second].second += fn[p.second].second;
            }
        }
    }
    

    /*rep(i,n) {
        cout << f1[i].first << ' ' << f1[i].second.val() << endl;
        cout << fn[i].first << ' ' << fn[i].second.val() << endl;
    }
    */

    rep(i,m) {
        if (f1[v[i][0]].first+fn[v[i][1]].first + v[i][2] == f1[1].first) {
            if (f1[v[i][0]].second * fn[v[i][1]].second == f1[1].second.val()) {
                cout << "SAD" << endl;
                continue;
            }
        }

        if (f1[v[i][1]].first+fn[v[i][0]].first + v[i][2] < f1[1].first) {
            cout << "HAPPY" << endl;
            continue;
        }

        cout << "SOSO" << endl;
    }

    return;

}


int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    solve();
}
accuracy: 1
time_ms: 100
memory_kb: 22464
final_rank: 2

code_snippet: #include <bits/extc++.h>

using ll = long long;
using namespace std;
#define REP(i, n) for (ll i = 0; i < (n); i++)

class Dijkstra {
 private:
  typedef pair<ll, ll> P;
  vector<vector<P>> G;
  ll V;
  ll INF = (1ll << 61);
  priority_queue<P, vector<P>, greater<P>> que;

 public:
  void init(int N, vector<pair<pair<ll, ll>, ll>> edge) {
    V = N;

    G.resize(V);
    for (int i = 0; i < (ll)edge.size(); i++) {
      ll from = edge[i].first.first, to = edge[i].first.second;
      ll cost = edge[i].second;
      G[from].push_back({cost, to});
    }
  }

  Dijkstra(int N, vector<pair<pair<ll, ll>, ll>> edge) { init(N, edge); }

  vector<ll> solve(ll s) {
    vector<ll> d(V, INF);
    d[s] = 0;
    que.push({0, s});

    while (!que.empty()) {
      P p = que.top();
      que.pop();
      ll v = p.second;
      if (d[v] < p.first) continue;
      for (ll i = 0; i < (ll)G[v].size(); i++) {
        P e = G[v][i];
        if (d[e.second] > d[v] + e.first) {
          d[e.second] = d[v] + e.first;
          que.push({d[e.second], e.second});
        }
      }
    }
    return d;
  }
};

template <class T>
bool chmax(T& x, const T& v) {
  if (x < v) {
    x = v;
    return true;
  } else {
    return false;
  }
}

template <class T>
bool chmin(T& x, const T& v) {
  if (x > v) {
    x = v;
    return true;
  } else {
    return false;
  }
}

template <class T>
std::istream& operator>>(std::istream& is, std::vector<T>& v) {
  for (T& x : v) is >> x;
  return is;
}

void solve() {
  ll N, M;
  cin >> N >> M;

  vector<pair<pair<ll, ll>, ll>> edge(M);
  vector<pair<pair<ll, ll>, ll>> edgeinv(M);
  REP(i, M) {
    ll a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    edge[i] = {{a, b}, c};
    edgeinv[i] = {{b, a}, c};
  }

  Dijkstra dijk(N, edge), dijkinv(N, edgeinv);
  vector<ll> d = dijk.solve(0);
  vector<ll> dinv = dijkinv.solve(1);

  // REP(i, N) { cout << d[i] << " "; }
  // cout << endl;
  // REP(i, N) { cout << dinv[i] << " "; }
  // cout << endl;

  // 最短経路DAG
  vector<vector<pair<ll, ll>>> G(N);
  vector<vector<pair<ll, ll>>> Ginv(N);
  vector<ll> DAGuse(N, 0);

  REP(i, M) {
    ll a = edge[i].first.first, b = edge[i].first.second;
    ll c = edge[i].second;

    if (d[a] + c + dinv[b] == d[1]) {
      // cout << a + 1 << " " << b + 1 << endl;
      G[a].push_back({b, c});
      Ginv[b].push_back({a, c});
      DAGuse[a] = 1;
      DAGuse[b] = 1;
    }
  }
  vector<ll> prime = {1'000'000'007, 1'000'000'009, 998'244'353};
  vector<vector<ll>> pat(prime.size(), vector<ll>(N, 0));
  vector<vector<ll>> patinv(prime.size(), vector<ll>(N, 0));

  REP(j, (ll)prime.size()) {
    ll P = prime[j];

    pat[j][0] = 1;

    queue<ll> que;
    vector<ll> nyuji(N, 0);
    REP(i, N) { nyuji[i] = Ginv[i].size(); }
    que.push(0);

    while (!que.empty()) {
      ll v = que.front();
      que.pop();

      for (pair<ll, ll> q : G[v]) {
        ll e = q.first;
        pat[j][e] = (pat[j][e] + pat[j][v]) % P;
        nyuji[e]--;
        if (nyuji[e] == 0) {
          que.push(e);
        }
      }
    }

    patinv[j][1] = 1;

    nyuji.assign(N, 0);
    REP(i, N) { nyuji[i] = G[i].size(); }
    que.push(1);

    while (!que.empty()) {
      ll v = que.front();
      que.pop();

      for (pair<ll, ll> q : Ginv[v]) {
        ll e = q.first;
        patinv[j][e] = (patinv[j][e] + patinv[j][v]) % P;
        nyuji[e]--;
        if (nyuji[e] == 0) {
          que.push(e);
        }
      }
    }
  }

  // REP(i, N) { cout << pat[0][i] << " "; }
  // cout << endl;
  // REP(i, N) { cout << patinv[0][i] << " "; }
  // cout << endl;

  REP(i, M) {
    ll a = edge[i].first.first, b = edge[i].first.second;
    ll c = edge[i].second;

    // DAGにいない辺
    if (d[a] + c + dinv[b] != d[1]) {
      ll newcost = d[b] + c + dinv[a];
      if (newcost < d[1]) {
        cout << "HAPPY" << endl;
      } else {
        cout << "SOSO" << endl;
      }

    } else {
      bool bridge = true;
      for (ll j = 0; j < (ll)prime.size(); j++) {
        ll P = prime[j];
        ll t = (pat[j][a] * patinv[j][b]) % P;
        if (t != pat[j][1]) bridge = false;
      }
      // DAGにいて橋じゃない辺
      if (!bridge) {
        cout << "SOSO" << endl;
      } else {
        // DAGにいて橋な辺
        cout << "SAD" << endl;
      }
    }
  }
}

int main() { solve(); }
accuracy: 1
time_ms: 190
memory_kb: 38104
final_rank: 10

code_snippet: #include<bits/stdc++.h>
#define rep(i,s,n) for (int i = (int)(s); i < (int)(n); i++)
#define all(v) begin(v),end(v)
using namespace std;
bool chmin(auto &a, auto b){ return a > b ? a = b, 1 : 0; }

bool chmax(auto &a, auto b){ return a < b ? a = b, 1 : 0; }
typedef long long ll;

struct low_link {
    low_link(const vector<vector<int>>&g) : n(g.size()), ord(n,-1), low(n), par(n,-1) {
        int k = 0;
        auto dfs = [&](auto&& self, int v) -> void {
            low[v] = ord[v] = k++;
            int cnt  =0;
            bool is_arti=false, is_second=false;
            for (auto nv:g[v]) {
                if (ord[nv]==-1) {
                    cnt++;
                    par[nv]=v;
                    self(self,nv);
                    chmin(low[v],low[nv]);
                    is_arti|=par[v]!=-1&&low[nv]>=ord[v];
                    if (ord[v]<low[nv]) {
                        _bridge.emplace_back(minmax(v,nv));
                    }
                }else if (nv!=par[v]||is_second) {
                    chmin(low[v],ord[nv]);
                }else {
                    is_second=true;
                }
            }
            is_arti|=par[v]==-1&&cnt>1;
            if (is_arti)_articulation.emplace_back(v);
        };
        dfs(dfs,0);

    }

    bool is_bridge(int u, int v) {
        if (par[v]!=u)swap(u,v);
        if (par[v]!=u)return false;
        return ord[u]<low[v];
    }
    int n;
    vector<int> ord,low,par,_articulation;
    vector<pair<int,int>> _bridge;
};

int main() {
    cin.tie(0)->sync_with_stdio(0);

    int n, m;
    cin >> n >> m;
    vector<int> a(m), b(m);
    vector<ll> c(m);
    vector ikeru(n, vector<pair<int,ll>>(0));
    vector ikeruinv(n, vector<pair<int,ll>>(0));
    rep(i,0,m) {
        cin >> a[i] >> b[i];
        cin >> c[i];
        a[i]--; b[i]--;
        ikeru[a[i]].push_back(pair(b[i],c[i]));
        ikeruinv[b[i]].push_back(pair(a[i],c[i]));
    }

    auto dijkstra = [](int n, int st, vector<vector<pair<int,ll>>> &ikeru) -> vector<ll> {
        vector<ll> d(n,1e18);
        priority_queue<pair<ll,int>> pq;
        d[st] = 0;
        pq.push(pair(-d[st],st));
        while (!pq.empty()) {
            auto[tmp,i]=pq.top();
            pq.pop();
            tmp=-tmp;
            if (tmp>d[i])continue;
            for (auto[j,c]:ikeru[i]) {
                ll targ = c+tmp;
                if (chmin(d[j],targ)) {
                    pq.push(pair(-d[j],j));
                }
            }
        }
        return d;
    };

    vector<ll> dstart = dijkstra(n, 0, ikeru);
    vector<ll> dend = dijkstra(n, 1, ikeruinv);


    vector<vector<int>> forlowlink(n, vector<int>(0));

    rep(i,0,m) {
        if (dstart[a[i]] + c[i] + dend[b[i]] == dstart[1]) {
            forlowlink[a[i]].push_back(b[i]);
            forlowlink[b[i]].push_back(a[i]);
           // cout << a[i] << ' ' << b[i] << endl;
        }
    }

    low_link llk(forlowlink);
    vector<bool> yabai(m);
    map<tuple<int,int,ll>,int> mp;
    rep(i,0,m) {
        mp[tuple(a[i],b[i],c[i])] += 1;
    }
    rep(i,0,m) {
        if (dstart[a[i]] + c[i] + dend[b[i]] == dstart[1]
            && llk.is_bridge(a[i],b[i])
            && mp[tuple(a[i],b[i],c[i]) ]== 1) {
            yabai[i] = 1;
        }
    }

    // 0 .. HAPPY
    // 1 .. SOSO
    // 2 .. SAD
    vector<int> ans(m);
    rep(i,0,m) {
        if (!yabai[i]) {
            if (dstart[b[i]] + c[i] + dend[a[i]] < dstart[1]) {
                ans[i] = 0;
            }else {
                ans[i] = 1;
            }
        }else {
            ans[i] = 2;
        }
    }

    rep(i,0,m) {
        if (ans[i] == 0) {
            cout << "HAPPY\n";
        }else if (ans[i]==1) {
            cout << "SOSO\n";
        }else {
            cout << "SAD\n";
        }
    }

}
accuracy: 1
time_ms: 80
memory_kb: 42892
final_rank: 5

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
using vi=vector<int>;
using vl=vector<ll>;
#define rep3(i,a,b,c) for(int i=(a);i<(b);i+=(c))
#define rep2(i,a,b) rep3(i,a,b,1)
#define rep1(i,n) rep2(i,0,n)
#define rep0(n) rep1(aaaaaaaaaa,n)
#define ov4(a,b,c,d,name,...) name
#define rep(...) ov4(__VA_ARGS__,rep3,rep2,rep1,rep0) (__VA_ARGS__)
#define per(i,a,b) for(ll i=(a)-1;i>=b;i--)
#define all(a) begin(a),end(a)
#define lb(v,x) (lower_bound(all(v),x)-begin(v)) 
#define fore(e,v) for(auto &&e: v)
#define sz(a) ((int)a.size())
#define eb emplace_back
template<typename T,typename S> bool chmin(T& a,const S& b){
    return a>b?a=b,1:0;
}
struct _{
    _(){
        cin.tie(0)->sync_with_stdio(0),cout.tie(0);
    };
}__;

template<typename G> struct LL{
    int n;
    const G g;
    vi ord,low,atri;
    vector<pii> bridge;
    LL(G g): n(sz(g)),g(g),ord(sz(g),-1),low(sz(g),-1){
        int k=0;
        rep(i,n){
            if(ord[i]==-1)k=dfs(i,k,-1);
        }
    }
    int dfs(int x,int k,int p){
        low[x]=(ord[x]=k++);
        int cnt=0;
        bool is_atri=false,second=false;
        fore(e,g[x]){
            if(ord[e]==-1){
                cnt++;
                k=dfs(e,k,x);
                chmin(low[x],low[e]);
                is_atri|=(p!=-1)&&(low[e]>=ord[x]);
                if(ord[x]<low[e])bridge.eb(minmax(x,e));
            }else if(e!=p or second){
                chmin(low[x],ord[e]);
            }else{
                second=true;
            }
        }
        is_atri|= p==-1 && cnt>1;
        if(is_atri)atri.eb(x);
        return k;
    }
};

int main(){
    int N,M;
    cin>>N>>M;
    vector G(N,vector(0,pll{}));
    vector rG(N,vector(0,pll{}));
    vector<array<ll,3>> E(M);
    rep(i,M){
        int A,B,C;
        cin>>A>>B>>C;
        --A,--B;
        G[A].push_back({B,C});
        rG[B].push_back({A,C});
        E[i]=array<ll,3>({A,B,C});
    }
    // cerr<<"input"<<endl;
    vl dist0(N,(ll)1e18);
    priority_queue<pll,vector<pll>,greater<pll>>pq;
    dist0[0]=0;
    pq.push(pll({0,0}));
    while(pq.size()){
        auto [d,v]=pq.top();
        pq.pop();
        if(dist0[v]<d)continue;
        for(auto [u,c]:G[v]){
            if(dist0[u]>d+c){
                dist0[u]=d+c;
                pq.push(pll{d+c,u});
            }
        }
    }
    // cerr<<"dist0"<<endl;

    vl dist1(N,(ll)1e18);
    dist1[1]=0;
    pq.push(pll{0,1});
    while(pq.size()){
        auto [d,v]=pq.top();
        pq.pop();
        if(dist1[v]<d)continue;
        for(auto [u,c]:rG[v]){
            if(dist1[u]>d+c){
                dist1[u]=d+c;
                pq.push(pll{d+c,u});
            }
        }
    }

    // cerr<<"dist1"<<endl;

    ll minDist=dist0[1];
    vector stG(N,vector(0,0));
    map<pii,int>stGidx;
    rep(i,M){
        auto [a,b,c]=E[i];
        if(dist0[a]+dist1[b]+c==minDist){
            if(stGidx.find(pii{a,b})!=stGidx.end()){
                stGidx[pii{a,b}]=-1;
                stGidx[pii{b,a}]=-1;
            }else{
                stG[a].push_back(b);
                stG[b].push_back(a);
                stGidx[pii{a,b}]=i;
                stGidx[pii{b,a}]=i;
            }
        }
    }
    vector<string> ans(M,"SOSO");
    rep(i,M){
        auto [a,b,c]=E[i];
        if(dist0[b]+dist1[a]+c<minDist){
            ans[i]="HAPPY";
        }
    }
    // for(auto i:ans)cerr<<i<<endl;
    LL llink(stG);
    for(auto i:llink.bridge){
        if(stGidx[i]!=-1){
            ans[stGidx[i]]="SAD";
        }
    }
    for(auto i:ans)cout<<i<<'\n';
}
accuracy: 1
time_ms: 170
memory_kb: 63132
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,a,b) for(ll i = a; i < b; i++)
#define all(a) (a).begin(), (a).end()
const ll INF = 1e18;

vector<ll> dijk(vector<vector<array<ll,3>>> g, int st){
    int n = g.size();
    vector<ll> dist(n, INF);
    dist[st] = 0;
    priority_queue<array<ll,2>> q;
    q.push({0, st});
    while(q.size()){
        auto [cst, nw] = q.top();
        q.pop();
        cst = -cst;
        if(dist[nw] != cst) continue;
        for(auto [to, cost, _]: g[nw]){
            if(dist[to] > cost + cst){
                dist[to] = cost + cst;
                q.push({-dist[to], to});
            }
        }
    }
    return dist;
}

int main(){
    int n,m;
    cin >> n >> m;
    vector<vector<array<ll,3>>> g(n),bg(n);
    vector<array<ll,3>> edge(m);
    rep(i,0,m){
        ll a,b,c;
        cin >> a >> b >> c;
        a--,b--;
        g[a].push_back({b,c,i});
        bg[b].push_back({a,c,i});
        edge[i] = {a,b,c};
    }
    vector<ll> dist1 = dijk(g, 0);
    vector<ll> dist2 = dijk(bg, 1);
    ll nwdist = dist1[1];


    vector<ll> should(m,0);
    
    priority_queue<array<ll,2>> q;
    q.push({0, 0});
    vector<int> searchd(n,0);
    while(q.size()){
        auto [_, nw] = q.top();
        q.pop();
        if(searchd[nw] == 1) continue;
        searchd[nw] = 1;
        for(auto [to, cost, _]: g[nw]){
            if(dist2[to] == dist2[nw] - cost){
                q.push({dist2[to], to});
            }
        }
        while(q.size() && q.top()[1] == nw) q.pop();
        if(q.size() == 1){
            for(auto [to, cost, i]: g[nw]){
                if(dist2[to] == dist2[nw] - cost){
                    should[i] = 1;
                }
            }
        }
    }

    rep(i,0,m) {
        auto [a,b,c] = edge[i];
        ll newdist = dist1[b] + c + dist2[a];
        if(newdist < nwdist) {
            cout << "HAPPY" << endl;
        }else if (!should[i] || (newdist != INF && newdist == nwdist)){
            cout << "SOSO" << endl;
        }else{
            cout << "SAD" << endl;
        }
    }
}
accuracy: 1
time_ms: 100
memory_kb: 24268
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,a,b) for(ll i = a; i < b; i++)
#define all(a) (a).begin(), (a).end()
const ll INF = 1e18;

vector<ll> dijk(vector<vector<array<ll,3>>> g, int st){
    int n = g.size();
    vector<ll> dist(n, INF);
    dist[st] = 0;
    priority_queue<array<ll,2>> q;
    q.push({0, st});
    while(q.size()){
        auto [cst, nw] = q.top();
        q.pop();
        cst = -cst;
        if(dist[nw] != cst) continue;
        for(auto [to, cost, _]: g[nw]){
            if(dist[to] > cost + cst){
                dist[to] = cost + cst;
                q.push({-dist[to], to});
            }
        }
    }
    return dist;
}

int main(){
    int n,m;
    cin >> n >> m;
    vector<vector<array<ll,3>>> g(n),bg(n);
    vector<array<ll,3>> edge(m);
    rep(i,0,m){
        ll a,b,c;
        cin >> a >> b >> c;
        a--,b--;
        g[a].push_back({b,c,i});
        bg[b].push_back({a,c,i});
        edge[i] = {a,b,c};
    }
    vector<ll> dist1 = dijk(g, 0);
    vector<ll> dist2 = dijk(bg, 1);
    ll nwdist = dist1[1];


    vector<ll> should(m,0);
    
    priority_queue<array<ll,2>> q;
    q.push({0, 0});
    vector<int> searchd(n,0);
    while(q.size()){
        auto [_, nw] = q.top();
        q.pop();
        if(searchd[nw] == 1) continue;
        searchd[nw] = 1;
        for(auto [to, cost, _]: g[nw]){
            if(dist2[to] == dist2[nw] - cost){
                q.push({-dist2[to], to});
            }
        }
        while(q.size() && q.top()[1] == nw) q.pop();
        if(q.size() == 1){
            for(auto [to, cost, i]: g[nw]){
                if(dist2[to] == dist2[nw] - cost){
                    should[i] = 1;
                }
            }
        }
    }

    rep(i,0,m) {
        auto [a,b,c] = edge[i];
        ll newdist = dist1[b] + c + dist2[a];
        if(newdist < nwdist) {
            cout << "HAPPY" << endl;
        }else if (!should[i] || (newdist != INF && newdist == nwdist)){
            cout << "SOSO" << endl;
        }else{
            cout << "SAD" << endl;
        }
    }
}
accuracy: 0.0851063829787234
time_ms: 100
memory_kb: 23668
final_rank: 16

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,a,b) for(ll i = a; i < b; i++)
#define all(a) (a).begin(), (a).end()
const ll INF = 1e18;

vector<ll> dijk(vector<vector<array<ll,3>>> g, int st){
    int n = g.size();
    vector<ll> dist(n, INF);
    dist[st] = 0;
    priority_queue<array<ll,2>> q;
    q.push({0, st});
    while(q.size()){
        auto [cst, nw] = q.top();
        q.pop();
        cst = -cst;
        if(dist[nw] != cst) continue;
        for(auto [to, cost, _]: g[nw]){
            if(dist[to] > cost + cst){
                dist[to] = cost + cst;
                q.push({-dist[to], to});
            }
        }
    }
    return dist;
}

int main(){
    int n,m;
    cin >> n >> m;
    vector<vector<array<ll,3>>> g(n),bg(n);
    vector<array<ll,3>> edge(m);
    rep(i,0,m){
        ll a,b,c;
        cin >> a >> b >> c;
        a--,b--;
        g[a].push_back({b,c,i});
        bg[b].push_back({a,c,i});
        edge[i] = {a,b,c};
    }
    vector<ll> dist1 = dijk(g, 0);
    vector<ll> dist2 = dijk(bg, 1);
    ll nwdist = dist1[1];


    vector<ll> should(m,0);
    
    priority_queue<array<ll,2>> q;
    q.push({0, 0});
    vector<int> searchd(n,0);
    while(q.size()){
        auto [_, nw] = q.top();
        q.pop();
        if(searchd[nw] == 1) continue;
        searchd[nw] = 1;
        for(auto [to, cost, _]: g[nw]){
            if(dist2[to] == dist2[nw] - cost){
                q.push({-dist2[to], to});
            }
        }
        if(q.size() == 1){
            for(auto [to, cost, i]: g[nw]){
                if(dist2[to] == dist2[nw] - cost){
                    should[i] = 1;
                }
            }
        }
    }

    rep(i,0,m) {
        auto [a,b,c] = edge[i];
        ll newdist = dist1[b] + c + dist2[a];
        if(newdist < nwdist) {
            cout << "HAPPY" << endl;
        }else if (!should[i] || (newdist != INF && newdist == nwdist)){
            cout << "SOSO" << endl;
        }else{
            cout << "SAD" << endl;
        }
    }
}
accuracy: 0.0851063829787234
time_ms: 100
memory_kb: 23668
final_rank: 16

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
using vi=vector<int>;
using vl=vector<ll>;
#define rep3(i,a,b,c) for(int i=(a);i<(b);i+=(c))
#define rep2(i,a,b) rep3(i,a,b,1)
#define rep1(i,n) rep2(i,0,n)
#define rep0(n) rep1(aaaaaaaaaa,n)
#define ov4(a,b,c,d,name,...) name
#define rep(...) ov4(__VA_ARGS__,rep3,rep2,rep1,rep0) (__VA_ARGS__)
#define per(i,a,b) for(ll i=(a)-1;i>=b;i--)
#define all(a) begin(a),end(a)
#define lb(v,x) (lower_bound(all(v),x)-begin(v)) 
#define fore(e,v) for(auto &&e: v)
#define sz(a) ((int)a.size())
#define eb emplace_back
template<typename T,typename S> bool chmin(T& a,const S& b){
    return a>b?a=b,1:0;
}
struct _{
    _(){
        cin.tie(0)->sync_with_stdio(0),cout.tie(0);
    };
}__;

template<typename G> struct LL{
    int n;
    const G g;
    vi ord,low,atri;
    vector<pii> bridge;
    LL(G g): n(sz(g)),g(g),ord(sz(g),-1),low(sz(g),-1){
        int k=0;
        rep(i,n){
            if(ord[i]==-1)k=dfs(i,k,-1);
        }
    }
    int dfs(int x,int k,int p){
        low[x]=(ord[x]=k++);
        int cnt=0;
        bool is_atri=false,second=false;
        fore(e,g[x]){
            if(ord[e]==-1){
                cnt++;
                k=dfs(e,k,x);
                is_atri|=(p!=-1)&&(low[e]>=ord[x]);
                if(ord[x]<low[e])bridge.eb(minmax(x,e));
            }else if(e!=p or second){
                chmin(low[x],ord[e]);
            }else{
                second=true;
            }
        }
        is_atri|=p==-1 && cnt>1;
        if(is_atri)atri.eb(x);
        return k;
    }
};

int main(){
    int N,M;
    cin>>N>>M;
    vector G(N,vector(0,pll{}));
    vector rG(N,vector(0,pll{}));
    vector<array<ll,3>> E(M);
    rep(i,M){
        int A,B,C;
        cin>>A>>B>>C;
        --A,--B;
        G[A].push_back({B,C});
        rG[B].push_back({A,C});
        E[i]=array<ll,3>({A,B,C});
    }
    // cerr<<"input"<<endl;
    vl dist0(N,(ll)1e18);
    priority_queue<pll,vector<pll>,greater<pll>>pq;
    dist0[0]=0;
    pq.push(pll({0,0}));
    while(pq.size()){
        auto [d,v]=pq.top();
        pq.pop();
        if(dist0[v]<d)continue;
        for(auto [u,c]:G[v]){
            if(dist0[u]>d+c){
                dist0[u]=d+c;
                pq.push(pll{d+c,u});
            }
        }
    }
    // cerr<<"dist0"<<endl;

    vl dist1(N,(ll)1e18);
    dist1[1]=0;
    pq.push(pll{0,1});
    while(pq.size()){
        auto [d,v]=pq.top();
        pq.pop();
        if(dist1[v]<d)continue;
        for(auto [u,c]:rG[v]){
            if(dist1[u]>d+c){
                dist1[u]=d+c;
                pq.push(pll{d+c,u});
            }
        }
    }

    // cerr<<"dist1"<<endl;

    ll minDist=dist0[1];
    vector stG(N,vector(0,0));
    map<pii,int>stGidx;
    rep(i,M){
        auto [a,b,c]=E[i];
        if(dist0[a]+dist1[b]+c==minDist){
            stG[a].push_back(b);
            stG[b].push_back(a);
            if(stGidx.find(pii{a,b})!=stGidx.end()){
                stGidx[pii{a,b}]=-1;
                stGidx[pii{b,a}]=-1;
            }else{
                stGidx[pii{a,b}]=i;
                stGidx[pii{b,a}]=i;
            }
        }
    }
    vector<string> ans(M,"SOSO");
    rep(i,M){
        auto [a,b,c]=E[i];
        if(dist0[b]+dist1[a]+c<minDist){
            ans[i]="HAPPY";
        }
    }
    // for(auto i:ans)cerr<<i<<endl;
    LL llink(stG);
    for(auto i:llink.bridge){
        if(stGidx[i]!=-1){
            ans[stGidx[i]]="SAD";
        }
    }
    for(auto i:ans)cout<<i<<'\n';
}
accuracy: 0.0851063829787234
time_ms: 160
memory_kb: 63124
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

ll mul(ll a, ll b, ll mod) { return a * b % mod; }

using vl = vector<ll>;

tuple<vl, vl, vl> solve(vector<vector<pair<ll, ll>>> &v, int s) {
    int n = v.size();
    vl dis(n, INF), cnt1(n, 0LL), cnt2(n, 0LL);
    cnt1[s] = cnt2[s] = 1;
    dis[s] = 0;
    multiset<pair<ll, ll>> ms;
    ms.insert({0, s});
    while(!ms.empty()) {
        auto [d, now] = *ms.begin();
        ms.erase(ms.begin());
        if(d > dis[now]) continue;
        for(auto [to, c] : v[now]) {
            if(dis[to] == d + c) {
                cnt1[to] += cnt1[now];
                cnt2[to] += cnt2[now];
                if(cnt1[to] >= MOD7) cnt1[to] -= MOD7;
                if(cnt2[to] >= MOD998) cnt2[to] -= MOD998;
            } else if(dis[to] > d + c) {
                dis[to] = d + c;
                cnt1[to] = cnt1[now];
                cnt2[to] = cnt2[now];
                ms.insert({dis[to], to});
            }
        }
    }
    return {dis, cnt1, cnt2};
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    ll n, m;
    cin >> n >> m;
    vector<vector<pair<ll, ll>>> v(n), inv(n);
    map<tuple<ll, ll, ll>, ll> mp;
    vector<tuple<ll, ll, ll>> edges;
    rep(i, m) {
        ll a, b, c;
        cin >> a >> b >> c;
        a --; b --;
        v[a].push_back({b, c});
        inv[b].push_back({a, c});
        mp[{a, b, c}] ++;
        edges.push_back({a, b, c});
    }
    
    auto [dis1, cnt1a, cnt1b] = solve(v, 0);
    auto [dis2, cnt2a, cnt2b] = solve(inv, 1);
    // rep(i, n) {
    //     cout << dis1[i] << " " << cnt1a[i] << " " << dis2[i] << " " << cnt2a[i] << endl;
    // }
    ll dis = dis1[1];
    ll cnt1A = cnt1a[1], cnt1B = cnt1b[1];
    for(auto [a, b, c] : edges) {
        if(dis1[b] + dis2[a] + c < dis) {
            cout << "HAPPY" << endl;
        } else if(mp[{a, b, c}] >= 2 or (mul(cnt1a[a], cnt2a[b], MOD7) != cnt1A or mul(cnt1b[a], cnt2b[b], MOD998) != cnt1B) or dis1[b] + dis2[a] + c == dis or dis1[a] + dis2[b] + c != dis) {
            cout << "SOSO" << endl;
        } else {
            cout << "SAD" << endl;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 32184
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;

constexpr long long INF = 2e18;

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    // input
    int N, M;
    cin >> N >> M;
    vector<int> A(M), B(M), C(M);
    vector<vector<pair<int, int>>> G(N), RG(N);
    for(int i = 0; i < M; i++) {
        cin >> A[i] >> B[i] >> C[i];
        A[i]--; B[i]--;
        G[A[i]].push_back({B[i], C[i]});
        RG[B[i]].push_back({A[i], C[i]});
    }

    //dijkstra1
    vector<long long> dist(N, INF);
    priority_queue<pair<long long, int>> pq;
    pq.push({0, 0});
    while(pq.size()) {
        auto [d, v] = pq.top(); pq.pop();

        if(dist[v] != INF) continue;
        dist[v] = -d;

        for(auto [nv, c] : G[v]) {
            if(dist[nv] != INF) continue;
            pq.push({d - c, nv});
        }
    }

    // dijkstra2
    vector<long long> rdist(N, INF);
    pq.push({0, 1});
    while(pq.size()) {
        auto [d, v] = pq.top(); pq.pop();

        if(rdist[v] != INF) continue;
        rdist[v] = -d;

        for(auto [nv, c] : RG[v]) {
            if(rdist[nv] != INF) continue;
            pq.push({d - c, nv});
        }
    }

    // edge graph
    vector<vector<pair<int, int>>> E(N);
    set<int> edges;
    for(int i = 0; i < M; i++) {
        if(dist[A[i]] + rdist[B[i]] + C[i] == dist[1]) {
            E[A[i]].push_back({B[i], i});
            E[B[i]].push_back({A[i], i});
            edges.insert(i);
        }
    }

    // lowlonk
    vector<int> ord(N, -1), low(N, -1);
    set<int> bridges;

    int cnt = 0;
    auto dfs = [&](auto f, int v, int p) -> void {
        ord[v] = cnt++;
        low[v] = ord[v];
        for(auto [nv, i] : E[v]) {
            if(nv == p) continue;
            // 木辺
            if(ord[nv] == -1) {
                f(f, nv, v);
                low[v] = min(low[v], low[nv]);
                if(ord[v] < low[nv]) bridges.insert(i);
            }

            // 後退辺
            else low[v] = min(low[v], ord[nv]);
        } 
    };

    for(int i = 0; i < N; i++) {
        if(ord[i] == -1) dfs(dfs, i, -1);
    }

    // ans
    for(int i = 0; i < M; i++) {
        if(bridges.count(i)) cout << "SAD\n";
        else if(edges.count(i)) cout << "SOSO\n";
        else if(dist[B[i]] + rdist[A[i]] + C[i] < dist[1]) cout << "HAPPY\n";
        else cout << "SOSO\n";
    }   

    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 44644
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
#define ALL(v) v.begin(),v.end()
#define dbg(x) cerr << #x << ": " << (x) << endl;

struct lowlink
{
    struct edge {int to, rev, stat;};
    int n, num;
    vector<vector<edge>> g;
    vector<int> ord, low, art;
    vector<pair<int, int>> bri;

    lowlink(int vsiz, vector<pair<int, int>> &e)
    {
        n = vsiz;
        g.resize(n);
        ord.resize(n);
        low.assign(n, n + 1);
        for (auto [a, b] : e)
        {
            edge e1{b, (int)g[b].size(), 0}, e2{a, (int)g[a].size(), 0};
            g[a].push_back(e1);
            g[b].push_back(e2);
        }
        num = 0;
        for (int i = 0; i < n; ++i)
        {
            if (ord[i] == 0)
            {
                dfs(i);
                ord[i] = -ord[i];
            }
        }
        for (int i = 0; i < n; ++i)
        {
            bool isroot = ord[i] < 0, flag = false;
            if (isroot)
            {
                ord[i] = -ord[i];
                int cnt = 0;
                for (auto &v : g[i]) cnt += v.stat == 1;
                flag = cnt > 1;
            }
            for (auto &v : g[i])
            {
                if (v.stat == 1)
                {
                    if (!isroot && ord[i] <= low[v.to]) flag = true;
                    if (ord[i] < low[v.to]) bri.push_back({i, v.to});
                }
            }
            if (flag) art.push_back(i);
        }
    }
private:
    void dfs(int now)
    {
        ord[now] = ++num;
        int mi = ord[now];
        for (auto &v : g[now])
        {
            if (ord[v.to] == 0)
            {
                v.stat = 1;
                g[v.to][v.rev].stat = 2;
                dfs(v.to);
            }
            if (v.stat == 0) mi = min(mi, ord[v.to]);
            else if (v.stat == 1) mi = min(mi, low[v.to]);
        }
        low[now] = mi;
    }
};

int main() {
    int n, m;
    cin >> n >> m;
    vector<pair<pair<int, int>, int>> e(m);
    vector<vector<pair<int, int>>> g(n), gr(n);
    for (int i = 0; i < m; ++i)
    {
        int a, b, c;
        cin >> a >> b >> c;
        --a, --b;
        e[i] = {{a, b}, c};
        g[a].push_back({b, c});
        gr[b].push_back({a, c});
    }
    vector<long long> dis1(n, 1e18), dis2(n, 1e18);
    {
        priority_queue<pair<long long, int>> pq;
        pq.push({0, 0});
        while (!pq.empty())
        {
            auto [d, now] = pq.top();
            pq.pop();
            if (dis1[now] <= -d) continue;
            dis1[now] = -d;
            for (auto [to, c] : g[now])
            {
                if (dis1[now] + c < dis1[to]) pq.push({-dis1[now] - c, to});
            }
        }
    }
    {
        priority_queue<pair<long long, int>> pq;
        pq.push({0, 1});
        while (!pq.empty())
        {
            auto [d, now] = pq.top();
            pq.pop();
            if (dis2[now] <= -d) continue;
            dis2[now] = -d;
            for (auto [to, c] : gr[now])
            {
                if (dis2[now] + c < dis2[to]) pq.push({-dis2[now] - c, to});
            }
        }
    }

    long long shlen = dis1[1];

    vector<string> ans(m);
    vector<int> eg(m);
    vector<pair<int, int>> tmpe;
    for (int i = 0; i < m; ++i)
    {
        if (dis1[e[i].first.first] + dis2[e[i].first.second] + e[i].second == shlen)
        {
            tmpe.emplace_back(e[i].first);
        }
        else
        {
            ans[i] = (dis1[e[i].first.second] + dis2[e[i].first.first] + e[i].second < shlen) ? "HAPPY" : "SOSO";
        }
    }

    lowlink lw(n, tmpe);
    set<pair<int, int>> st(lw.bri.begin(), lw.bri.end());
    for (int i = 0; i < m; ++i)
    {
        if (ans[i] == "")
        {
            ans[i] = (st.find(e[i].first) != st.end() ? "SAD" : "SOSO");
        }
    }
    for (int i = 0; i < m; ++i) cout << ans[i] << endl;
}
accuracy: 1
time_ms: 170
memory_kb: 39504
final_rank: 8

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (ll i = (ll)(a); i < (ll)(b); i++)
#define rrep(i, a, b) for (ll i = (ll)(b)-1; i >= (ll)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

struct LowLink{
    const int n; vector<vector<int>> g;
    vector<int> used,ord,low,id,arti;
    LowLink(const int& _n=0):n(_n),g(n),
        used(n,0),ord(n,0),low(n,0),id(n,-1){
    }
    void add_edge(int u,int v){
        g[u].emplace_back(v); g[v].emplace_back(u);
     }
    void dfs(int v,int p,int& k){
        used[v]=1; low[v]=ord[v]=k++;
        bool isarti=0;
        int cnt=0,sub=0;
        for(auto& to:g[v]){
            if(to==p and (++sub)<=1)continue;
            if(!used[to]){
                cnt++; dfs(to,v,k);
                chmin(low[v],low[to]);
                isarti|=(p>=0&&low[to]>=ord[v]);
            }
            else chmin(low[v],ord[to]);
        }
        isarti|=(p==-1&&cnt>1);
        if(isarti)arti.push_back(v);
    }
    void dfs2(int v,int p,int& k){
        if(p!=-1 and ord[p]>=low[v])id[v]=id[p];
        else id[v]=k++;
        for(auto& to:g[v])if(id[to]==-1)dfs2(to,v,k);
    }
    int run(){
        int k=0; rep(i,0,n)if(!used[i])dfs(i,-1,k);
        k=0; rep(i,0,n)if(id[i]==-1)dfs2(i,-1,k);
        return k;
    }
};

/**
 * @brief Lowlink
 */

vector<ll> Dijkstra(vector<vector<pair<ll,int>>>& G, int S) {
    int N = G.size();
    vector<ll> DP(N, INF);
    priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<pair<ll,int>>> PQ;
    DP[S] = 0;
    PQ.push({0LL,S});
    while(!PQ.empty()) {
        auto [D,P] = PQ.top();
        PQ.pop();
        if (DP[P] < D) continue;
        for (auto E : G[P]) {
            auto [DD, NP] = E;
            ll ND = D+DD;
            if (chmin(DP[NP],ND)) {
                PQ.push({ND,NP});
            }
        }
    }
    return DP;
}

int main() {
    int N, M;
    cin >> N >> M;
    vector<int> A(M), B(M);
    vector<ll> C(M);
    vector<vector<pair<ll,int>>> G(N), H(N);
    rep(i,0,M) cin >> A[i] >> B[i] >> C[i], A[i]--, B[i]--;
    rep(i,0,M) {
        G[A[i]].push_back({C[i],B[i]});
        H[B[i]].push_back({C[i],A[i]});
    }
    auto DPS = Dijkstra(G,0), DPT = Dijkstra(H,1);
    LowLink L(N);
    rep(i,0,M) {
        if (DPS[A[i]] + DPT[B[i]] + C[i] == DPS[1]) L.add_edge(A[i],B[i]);
    }
    L.run();
    rep(i,0,M) {
        if (DPS[B[i]] + DPT[A[i]] + C[i] < DPS[1]) cout << "HAPPY" << endl;
        else if (DPS[B[i]] + DPT[A[i]] + C[i] == DPS[1]) cout << "SOSO" << endl;
        else if (DPS[A[i]] + DPT[B[i]] + C[i] != DPS[1]) cout << "SOSO" << endl;
        else {
            if (L.ord[A[i]] < L.ord[B[i]]) {
                if (L.ord[A[i]] < L.low[B[i]]) {
                    cout << "SAD" << endl;
                }
                else {
                    cout << "SOSO" << endl;
                }
            }
            else {
                if (L.ord[B[i]] < L.low[A[i]]) {
                    cout << "SAD" << endl;
                }
                else {
                    cout << "SOSO" << endl;
                }
            }
        }
    }
}
accuracy: 1
time_ms: 150
memory_kb: 34112
final_rank: 7