Problem:
Score : 1100 points

Problem Statement

You are given a directed graph with N vertices and M edges.
The vertices are numbered 1, 2, ..., N, and the edges are numbered 1, 2, ..., M.
Edge i points from Vertex a_i to Vertex b_i.

For each edge, determine whether the reversion of that edge would change the number of the strongly connected components in the graph.

Here, the reversion of Edge i means deleting Edge i and then adding a new edge that points from Vertex b_i to Vertex a_i.

Constraints

2 \leq N \leq 1000

1 \leq M \leq 200,000

1 \leq a_i, b_i \leq N

a_i \neq b_i

If i \neq j, then a_i \neq a_j or b_i \neq b_j.

Input

Input is given from Standard Input in the following format:

N M
a_1 b_1
a_2 b_2
:
a_M b_M

Output

Print M lines. In the i-th line, if the reversion of Edge i would change the number of the strongly connected components in the graph, print diff; if it would not, print same.

Sample Input 1

3 3
1 2
1 3
2 3

Sample Output 1

same
diff
same

The number of the strongly connected components is 3 without reversion of edges, but it will become 1 if Edge 2 is reversed.

Sample Input 2

2 2
1 2
2 1

Sample Output 2

diff
diff

Reversion of an edge may result in multiple edges in the graph.

Sample Input 3

5 9
3 2
3 1
4 1
4 2
3 5
5 3
3 4
1 2
2 5

Sample Output 3

same
same
same
same
same
diff
diff
diff
diff

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

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

#define ll long long
#define sd(x) scanf("%d", &(x))
#define pii pair<int, int>
#define F first
#define S second

#ifdef LOCAL
#define cerr cout
#else
#endif

#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
	cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
	const char* comma = strchr(names + 1, ',');cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...)
#endif

const int N = 1005;
const int M = 200005;
bool not_necessary[N][N];
vector<int> con[N];
int a[M], b[M];
int vis[N];
int fe[N];

struct graph {
  int n;
  vector<vector<int>> adj;
  graph(int n) : n(n), adj(n) { }
  void add_edge(int src, int dst) {
    adj[src].push_back(dst);
  }

  vector<vector<int>> strongly_connected_components() {
    vector<vector<int>> scc;
    vector<int> S, B, I(n);
    function<void(int)> dfs = [&](int u) {
      B.push_back(I[u] = S.size());
      S.push_back(u);
      for (int v: adj[u]) {
        if (!I[v]) dfs(v);
        else while (I[v] < B.back()) B.pop_back();
      }
      if (I[u] == B.back()) {
        scc.push_back({});
        B.pop_back();
        for (; I[u] < S.size(); S.pop_back()) {
          scc.back().push_back(S.back());
          I[S.back()] = n + scc.size();
        }
      }
    };
    for (int u = 0; u < n; ++u)
      if (!I[u]) dfs(u);
    return scc; // I[u] - n is the index of u
  }
};


int main(){
	int n, m; sd(n); sd(m);
	graph g(n + 1);
	for(int i = 1; i <= m; i++){
		sd(a[i]);
		sd(b[i]);
		con[a[i]].push_back(b[i]);
		g.add_edge(a[i], b[i]);
	}
	vector<vector<int>> comp = g.strongly_connected_components();
	vector<int> where(n + 1);
	for(int i = 0; i < comp.size(); i++)
		for(auto it : comp[i])
			where[it] = i;
	queue<pii> q;
	for(int i = 1; i <= n; i++){
		memset(vis, 0, sizeof vis);
		for(int v : con[i]){
			q.push({v, v});
			vis[v] = 1;
			fe[v] = v;
		}
		while(!q.empty()){
			auto it = q.front();
			q.pop();
			int u = it.F, firstEdge = it.S;
			for(int v : con[u]){
				if(v == i || vis[v] >= 2) continue;
				if(vis[v] == 1 && firstEdge == fe[v]) continue;
				q.push({v, firstEdge});
				if(vis[v] == 0)
					fe[v] = firstEdge;
				vis[v]++;
			}
		}
		for(int v : con[i]) if(vis[v] == 2){
			not_necessary[i][v] = 1;
		}
	}
	for(int i = 1; i <= m; i++){
		printf( (not_necessary[a[i]][b[i]] ^ (where[a[i]] != where[b[i]] )) ? "same\n" : "diff\n");
	}
}