// Arup Guha
// 9/8/2026
// Making Connections: Disjoint Set Application

import java.util.*;
import java.io.*;

public class connect {

	public static void main(String[] args) throws IOException {
	
		//Scanner stdin = new Scanner(System.in);
		BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer tok = new StringTokenizer(stdin.readLine());
		int n = Integer.parseInt(tok.nextToken());
		int numOp = Integer.parseInt(tok.nextToken());
		
		// Create the disjoint set.
		djset mine = new djset(n);
		
		// Store answer here for faster output.
		StringBuffer sb = new StringBuffer();
		
		// Process operations.
		for (int i=0; i<numOp; i++) {
			
			// Get operation.
			tok = new StringTokenizer(stdin.readLine());
			int op = Integer.parseInt(tok.nextToken());
			
			// Add edge.
			if (op == 1) {
				int u = Integer.parseInt(tok.nextToken())-1;
				int v = Integer.parseInt(tok.nextToken())-1;
				mine.union(u,v);
			}
			
			// Output connectivity.
			else {
				
				// Get numerator and denominator for our fraction.
				long numerator = mine.getSumSq();
				long denominator = mine.getNumComp();
				
				// Reduce!
				long div = gcd(numerator, denominator);
				numerator /= div;
				denominator /= div;
				
				/*** First statement is slow output, second is to speed up output. ***/
				//System.out.println(numerator+"/"+denominator);
				sb.append(numerator+"/"+denominator+"\n");
			}
			
		}
		
		// Print all output with one print.
		System.out.print(sb);
	}
	
	// Returns the greatest common divisor of a and b.
	public static long gcd(long a, long b) {
		return b == 0 ? a : gcd(b, a%b);
	}
}


class djset {

	private int numComp;
	private int n;
	private int[] parent;
	private int[] treeSize;
	private long sumSq;

	// Constructor for a djset set of size n.
	public djset(int myn) {
		
		// Basic set up.
		n = myn;
		numComp = n;
		parent = new int[n];
		treeSize = new int[n];
		
		// Each tree size is 1, parent is itself.
		for (int i=0; i<n; i++) {
			parent[i] = i;
			treeSize[i] = 1;
		}
		
		// Sum of n 1's...
		sumSq = n;
	}
	
	public int getNumComp() {
		return numComp;
	}
	
	public long getSumSq() {
		return sumSq;
	}
	
	public int find(int u) {
	
		// We got to the root, return it.
		if (parent[u] == u) return u;
		
		// Get the answer, reset u's parent, and return.
		/*** This is path compression. ***/
		return parent[u] = find(parent[u]);
	}
	
	public boolean union(int u, int v) {
	
		// Update with roots.
		u = find(u);
		v = find(v);
		
		// No union operation actually conducted.
		if (u == v) return false;
		
		// Attach v to u.
		parent[v] = u;
		numComp--;
		
		// Get squares of all three tree sizes involved.
		long oldU = treeSize[u];
		long oldV = treeSize[v];
		treeSize[u] += treeSize[v];
		long newU = treeSize[u];
		
		// Update sum of squares accordingly.
		sumSq = sumSq - oldU*oldU - oldV*oldV + newU*newU;
		return true;
	}
}