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 Java8 (OpenJDK 1.8.0) (judge verdict: Wrong Answer)

import java.io.IOException; 
import java.io.InputStream; 
import java.io.PrintWriter; 
import java.util.*;

class SCC{
	List<Integer>[] edges;
	List<Integer>[] redges;
	boolean[] used;
	int[] comp;
	int comp_num=0;
	int n;

	List<Integer>[] scc_edges;
	List<Integer> sorted_comp;
	// 最後尾までの最大距離
	int[] rank;

	SCC(int n){
		this.n=n;
		edges = new ArrayList[n];
		redges=new ArrayList[n];
		comp = new int[n];
		used=new boolean[n];
		for(int i=0;i<n;++i)edges[i]=new ArrayList<>();
		for(int i=0;i<n;++i)redges[i]=new ArrayList<>();
		Arrays.fill(comp, -1);
	}
	void add_edges(int u, int v){
		edges[u].add(v);
		redges[v].add(u);
	}
	void scc(){
		Deque<Integer> visit = new ArrayDeque<>();
		Arrays.fill(used, false);
		for(int i=0;i<n;++i)if(!used[i])dfs1(i, visit);
		while(!visit.isEmpty()){
			int v = visit.pollLast();
			if(comp[v]>=0)continue;
			dfs2(v);
			comp_num++;
		}
	}

	void topoSort(){
		Set<Integer>[] ed = new Set[n];
		for(int i=0;i<n;++i)ed[i] = new HashSet<>();
		for(int i=0;i<n;++i)for(int u: edges[i])if(comp[i]!=comp[u])ed[comp[i]].add(comp[u]);
		scc_edges = new ArrayList[n];
		for(int i=0;i<n;++i)scc_edges[i]=new ArrayList<>();
		for(int i=0;i<n;++i)for(int u: ed[i])scc_edges[i].add(u);
		Arrays.fill(used, false);
		sorted_comp = new ArrayList<>();
		for(int i=0;i<comp_num;++i)if(!used[i])dfs3(i, sorted_comp);
		Collections.reverse(sorted_comp);

//		for(int i=0;i<n;++i)System.out.print(comp[i]+" ");
//		System.out.println();
//		for(int i=0;i<comp_num;++i)for(int u: scc_edges[i])System.out.println(i+" to "+u);
		
		rank = new int[comp_num];
		Arrays.fill(rank, -1);
		for(int i=0;i<comp_num;++i)dfs4(i);
	}

	void dfs1(int v, Deque que){
		used[v]=true;
		for(int u: edges[v])if(!used[u])dfs1(u, que);
		que.addLast(v);
	}
	void dfs2(int v){
		comp[v]=comp_num;
		for(int u: redges[v])if(comp[u]<0)dfs2(u);
	}
	void dfs3(int v, List list){
		used[v]=true;
		for(int u: scc_edges[v])if(!used[u])dfs3(u, list);
		list.add(v);
	}
	int dfs4(int v){
		if(rank[v]>=0)return rank[v];
		for(int u: scc_edges[v]){
			System.out.println(v+" "+u);
			rank[v] = Math.max(rank[v], dfs4(u));
		}
		rank[v]++;
		return rank[v];
	}
}

class Main{

	static void solve(){
		int n = ni(), m=ni();
		SCC scc = new SCC(n);
		int[] a = new int[m];
		int[] b = new int[m];
		int[] in = new int[n];
		int[] ou = new int[n];
		for(int i=0;i<m;++i){
			a[i]=ni()-1;
			b[i]=ni()-1;
			scc.add_edges(a[i], b[i]);
		}
		scc.scc();
		scc.topoSort();
		for(int i=0;i<n;++i){
			for(int u: scc.edges[i]){
				if(scc.comp[i]==scc.comp[u]){
					ou[i]++;in[u]++;
				}
			}
		}

		for(int i=0;i<m;++i){
			if(scc.comp[a[i]]==scc.comp[b[i]]){
				if(ou[a[i]]>1 && in[b[i]]>1){
					out.println("same");
				}else{
					out.println("diff");
				}
			}else{
				if(scc.rank[scc.comp[a[i]]] - scc.rank[scc.comp[b[i]]]==1){
					out.println("same");
				}else{
					out.println("diff");
				}
			}
		}
 
	}
 
 
 
 
	public static void main(String[] args){ 
		 solve(); 
		 out.flush(); 
	 } 
	 private static InputStream in = System.in; 
	 private static PrintWriter out = new PrintWriter(System.out); 
 
	 private static final byte[] buffer = new byte[1<<15]; 
	 private static int ptr = 0; 
	 private static int buflen = 0; 
	 private static boolean hasNextByte(){ 
		 if(ptr<buflen)return true; 
		 ptr = 0; 
		 try{ 
			 buflen = in.read(buffer); 
		 } catch (IOException e){ 
			 e.printStackTrace(); 
		 } 
		 return buflen>0; 
	 } 
	 private static int readByte(){ if(hasNextByte()) return buffer[ptr++]; else return -1;} 
	 private static boolean isSpaceChar(int c){ return !(33<=c && c<=126);} 
	 private static int skip(){int res; while((res=readByte())!=-1 && isSpaceChar(res)); return res;} 
 
	 private static double nd(){ return Double.parseDouble(ns()); } 
	 private static char nc(){ return (char)skip(); } 
	 private static String ns(){ 
		 StringBuilder sb = new StringBuilder(); 
		 for(int b=skip();!isSpaceChar(b);b=readByte())sb.append((char)b); 
		 return sb.toString(); 
	 } 
	 private static int[] nia(int n){ 
		 int[] res = new int[n]; 
		 for(int i=0;i<n;++i)res[i]=ni(); 
		 return res; 
	 } 
	 private static long[] nla(int n){ 
		 long[] res = new long[n]; 
		 for(int i=0;i<n;++i)res[i]=nl(); 
		 return res; 
	 } 
	 private static int ni(){ 
		 int res=0,b; 
		 boolean minus=false; 
		 while((b=readByte())!=-1 && !((b>='0'&&b<='9') || b=='-')); 
		 if(b=='-'){ 
			 minus=true; 
			 b=readByte(); 
		 } 
		 for(;'0'<=b&&b<='9';b=readByte())res=res*10+(b-'0'); 
		 return minus ? -res:res; 
	 } 
	 private static long nl(){ 
		 long res=0,b; 
		 boolean minus=false; 
		 while((b=readByte())!=-1 && !((b>='0'&&b<='9') || b=='-')); 
		 if(b=='-'){ 
			 minus=true; 
			 b=readByte(); 
		 } 
		 for(;'0'<=b&&b<='9';b=readByte())res=res*10+(b-'0'); 
		 return minus ? -res:res; 
	} 
}