public void contract(Edge edge) {

		if (Debug.ON) {
			System.out.println("Contracting ");
			System.out.println("Choosing Edge " + edge.tail.id + " -- "
					+ edge.head.id);
		}

		// THE FOLLOWING CODES MUST BE CHANGED WHEN DEALING WITH DIRECTED GRAPH

		int group = -1;
		if (edge.tail.gid != -1) {
			group = edge.tail.gid;
			if (edge.head.gid != -1)
				mergeGroups(edge.tail.gid, edge.head.gid);
			else
				edge.head.gid = group;
		} else if (edge.head.gid != -1) {
			group = edge.head.gid;
			if (edge.tail.gid != -1)
				mergeGroups(edge.head.gid, edge.tail.gid);
			else
				edge.tail.gid = group;
		} else {
			group = gid;
			gid++;
			groups.put(group, new HashSet<Integer>());
			edge.tail.gid = group;
			edge.head.gid = group;
		}

		if (groups.get(group).add(edge.tail.id) == true)
			nodesNum--;
		if (groups.get(group).add(edge.head.id) == true)
			nodesNum--;

		if (nodesNum < 0)
			nodesNum = 0;

		// contract edges from its tail's adjacency list
		contractEdge(edge.tail, group);
		// contract edges from its head's adjacency list
		contractEdge(edge.head, group);

		if (Debug.ON) {
			System.out.println("Edges " + edgesNum + " Groups " + groups.size()
					+ " Nodes " + nodesNum);
			System.out.println();
		}
	}