Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], skipTags: ["script","noscript","style","textarea","code"], processEscapes: true }});

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

Solution in C++ (judge verdict: Wrong Answer)

#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 100000


struct Edge{
	int from,to,cost;
};

struct Data{
	Data(int arg_node_id,int arg_sum_cost){
		node_id = arg_node_id;
		sum_cost = arg_sum_cost;
	}

	bool operator<(const struct Data &arg) const{
		return sum_cost > arg.sum_cost;
	}
	int node_id,sum_cost;
};

struct Info{
	Info(int arg_to,int arg_cost,int arg_edge_id){
		to = arg_to;
		cost = arg_cost;
		edge_id = arg_edge_id;
	}
	int to,cost,edge_id;
};

int V,E,number;
int order[NUM],lowlink[NUM];
int min_cost[NUM],rev_min_cost[NUM];
bool visited[NUM],in_MIN_PATH[NUM];
Edge edge[NUM];
vector<Info> G[NUM],rev_G[NUM],MIN_G[NUM];
vector<int> SHORTEST_EDGES[NUM];

void recursive(int node_id){

	order[node_id] = number++;
	lowlink[node_id] = order[node_id];

	int next_node;

	for(int i = 0; i < MIN_G[node_id].size(); i++){

		next_node = MIN_G[node_id][i].to;

		if(order[next_node] == -1){

			visited[MIN_G[node_id][i].edge_id] = true;
			recursive(next_node);
			lowlink[node_id] = min(lowlink[node_id],lowlink[next_node]);

		}else if(visited[MIN_G[node_id][i].edge_id] == false){

			lowlink[node_id] = min(lowlink[node_id],order[next_node]);
		}
	}
}

void dijkstra_NORMAL(){
	int start = 0,goal = 1;

	for(int i = 0; i < V; i++)min_cost[i] = BIG_NUM;
	min_cost[start] = 0;

	priority_queue<Data> Q;

	Q.push(Data(start,0));

	int next_node;

	while(!Q.empty()){

		if(Q.top().node_id == goal){
			Q.pop();
		}else if(Q.top().sum_cost > min_cost[Q.top().node_id]){
			Q.pop();
		}else{

			for(int i = 0; i < G[Q.top().node_id].size(); i++){
				next_node = G[Q.top().node_id][i].to;

				if(min_cost[next_node] > Q.top().sum_cost+G[Q.top().node_id][i].cost){

					min_cost[next_node] = Q.top().sum_cost+G[Q.top().node_id][i].cost;
					SHORTEST_EDGES[next_node].clear();
					SHORTEST_EDGES[next_node].push_back(G[Q.top().node_id][i].edge_id);
					Q.push(Data(next_node,min_cost[next_node]));

				}else if(min_cost[next_node] == Q.top().sum_cost+G[Q.top().node_id][i].cost){

					SHORTEST_EDGES[next_node].push_back(G[Q.top().node_id][i].edge_id);
				}
			}
			Q.pop();
		}
	}
}

void dijkstra_REVERSE(){
	int start = 1,goal = 0;

	for(int i = 0; i < V; i++)rev_min_cost[i] = BIG_NUM;
	rev_min_cost[start] = 0;

	priority_queue<Data> Q;

	Q.push(Data(start,0));

	int next_node;

	while(!Q.empty()){

		if(Q.top().node_id == goal){
			Q.pop();
		}else if(Q.top().sum_cost > rev_min_cost[Q.top().node_id]){
			Q.pop();
		}else{

			for(int i = 0; i < rev_G[Q.top().node_id].size(); i++){
				next_node = rev_G[Q.top().node_id][i].to;

				if(rev_min_cost[next_node] > Q.top().sum_cost+rev_G[Q.top().node_id][i].cost){

					rev_min_cost[next_node] = Q.top().sum_cost+rev_G[Q.top().node_id][i].cost;
					Q.push(Data(next_node,rev_min_cost[next_node]));
				}
			}
			Q.pop();
		}
	}
}

int main(){

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

	for(int i = 0; i < E; i++){
		scanf("%d %d %d",&edge[i].from,&edge[i].to,&edge[i].cost);
		edge[i].from--;
		edge[i].to--;
		G[edge[i].from].push_back(Info(edge[i].to,edge[i].cost,i));
		rev_G[edge[i].to].push_back(Info(edge[i].from,edge[i].cost,i));
	}

	dijkstra_NORMAL();
	dijkstra_REVERSE();

	int tmp_id;

	for(int i = 0; i < E; i++)in_MIN_PATH[i] = false;

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

		for(int k = 0; k < SHORTEST_EDGES[i].size(); i++){
			tmp_id =  SHORTEST_EDGES[i][k];
			in_MIN_PATH[tmp_id] = true;
			MIN_G[edge[tmp_id].from].push_back(Info(edge[tmp_id].to,edge[tmp_id].cost,tmp_id));
		}
	}

	number = 0;

	for(int i = 0; i < V; i++){
		order[i] = -1;
		lowlink[i] = -1;
	}

	for(int i = 0; i < E; i++){
		visited[i] = false;
	}
	recursive(0);



	int from,to,goal = 1;


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

		if(min_cost[goal] == BIG_NUM){

			if(min_cost[edge[i].to]+edge[i].cost+rev_min_cost[edge[i].from] < BIG_NUM){
				printf("HAPPY\n");
				continue;
			}else{
				printf("SOSO\n");
			}

			continue;
		}

		if((min_cost[edge[i].to] != BIG_NUM) && (rev_min_cost[edge[i].from] != BIG_NUM)
				&& (min_cost[edge[i].to]+edge[i].cost+rev_min_cost[edge[i].from]) < min_cost[goal]){
			printf("HAPPY\n");
			continue;
		}

		if(in_MIN_PATH[i] == false){
			printf("SOSO\n");
			continue;
		}


		from = edge[i].from;
		to = edge[i].to;
		if(order[to] < order[from]){
			swap(from,to);
		}
		if(order[from] < lowlink[to] && min_cost[from]+edge[i].cost+rev_min_cost[to] == min_cost[goal]){
			printf("SAD\n");
			continue;
		}

		printf("SOSO\n");

	}

	return 0;
}