public class ArcArrowSymbol {

	private double beta;
	private int sideDistance;

	public ArcArrowSymbol() {
		beta = 0;
		sideDistance = 0;
	}

	public double getBeta() {
		return beta;
	}

	public void setBeta(double beta) {
		this.beta = beta;
	}

	public int getSideDistance() {
		return sideDistance;
	}

	public void setSideDistance(int sideDistance) {
		this.sideDistance = sideDistance;
	}

} public class ArcCircleMiddleDistanceSymbol extends ArcSymbol {

	private double middleDistance;

	public ArcCircleMiddleDistanceSymbol() {
		middleDistance = 0;
	}

	public double getMiddleDistance() {
		return middleDistance;
	}

	public void setMiddleDistance(double middleDistance) {
		this.middleDistance = middleDistance;
	}

	@Override
	public boolean isCircleMiddleDistanceSymbol() {
		return true;
	}

} public class ArcCircleStartAngleSymbol extends ArcSymbol {

	private double startAngle;

	public ArcCircleStartAngleSymbol() {
		startAngle = 0;
	}

	public double getStartAngle() {
		return startAngle;
	}

	public void setStartAngle(double startAngle) {
		this.startAngle = startAngle;
	}

	@Override
	public boolean isCircleStartAngleSymbol() {
		return true;
	}

} public class ArcLineSymbol extends ArcSymbol {

	@Override
	public boolean isLineSymbol() {
		return true;
	}

} public abstract class ArcSymbol {

	/**
	 * 
	 * @return true if this representation is a line linking its two endings.
	 */
	public boolean isLineSymbol() {
		return false;
	}

	/**
	 * 
	 * @return true if this representation is a circular curve defined with the
	 *         angle separating the segment linking its two endings and the
	 *         tangent of the curve at one of the endings.
	 */
	public boolean isCircleStartAngleSymbol() {
		return false;
	}

	/**
	 * 
	 * @return true if this representation is a circular curve defined with the
	 *         maximal distance from the segment linking its ending is defined.
	 */
	public boolean isCircleMiddleDistanceSymbol() {
		return false;
	}
} public class NodeCircleSymbol extends NodeSymbol {

	public static final int DEFAULT_RADIUS = 25;

	int radius;

	public NodeCircleSymbol() {
		radius = DEFAULT_RADIUS;
	}

	public int getRadius() {
		return radius;
	}

	public void setRadius(int radius) {
		this.radius = radius;
	}

	@Override
	public boolean isCircle() {
		return true;
	}

} public class NodeSquareSymbol extends NodeSymbol {

	public static final int DEFAULT_SIDE_LENGTH = 50;

	int sideLength;

	public NodeSquareSymbol() {
		super();
		this.sideLength = DEFAULT_SIDE_LENGTH;
	}

	public int getSideLength() {
		return sideLength;
	}

	public void setSideLength(int sideLength) {
		this.sideLength = sideLength;
	}

	@Override
	public boolean isSquare() {
		return true;
	}

} public abstract class NodeSymbol {

	/**
	 * 
	 * @return true if this representation is a circle.
	 */
	public boolean isCircle() {
		return false;
	}

	/**
	 * 
	 * @return true if this representation is a square.
	 */
	public boolean isSquare() {
		return false;
	}
} public class Collections2 {

	/**
	 * Source : http://eyalsch.wordpress.com/2010/04/01/random-sample
	 * 
	 * @param col
	 * @param size
	 * @return a random subset of the set col which size is size.
	 */
	public static <T> Set<T> randomSubset(Set<T> col, int size) {
		if (size == 0) {
			return new HashSet<T>();
		}
		int s = col.size();
		int dif = s - size;
		if (dif == 0) {
			return new HashSet<T>(col);
		}
		if (dif >= 0 && dif < s) {
			HashSet<T> res = new HashSet<T>();
			int visited = 0;
			Iterator<T> it = col.iterator();
			T item;

			HighQualityRandom rand = new HighQualityRandom();

			while (size > 0) {
				item = it.next();
				if (rand.nextDouble() < ((double) size) / (s - visited)) {
					res.add(item);
					size--;
				}
			}
			return res;
		}
		return null;
	}

	/**
	 * Source : http://eyalsch.wordpress.com/2010/04/01/random-sample
	 * 
	 * @param col
	 * @param size
	 * @return a random subset of the list col which size is size.
	 */
	public static <T> Set<T> randomSubset(List<T> col, int size) {
		if (size == 0) {
			return new HashSet<T>();
		}
		int s = col.size();
		int dif = s - size;
		if (dif == 0) {
			return new HashSet<T>(col);
		}
		if (dif >= 0 && dif < s) {
			HashSet<T> res = new HashSet<T>();
			T item;

			HighQualityRandom rand = new HighQualityRandom();

			for (int i = dif; i < s; i++) {
				item = col.get(rand.nextInt(i + 1));
				if (!res.add(item))
					res.add(col.get(i));
			}
			return res;
		}
		return null;
	}

	/**
	 * @param col
	 * @return a random element of the list col.
	 */
	public static <T> T randomElement(List<T> col) {
		int s = col.size();
		if (s == 0)
			return null;
		int i = Math2.randomInt(s);
		return col.get(i);
	}

	/**
	 * @param k
	 * @return an array containing every integers from 0 to k-1, in that order.
	 */
	public static int[] range(int k) {
		int[] ar = new int[k];
		for (int i = 0; i < k; i++) {
			ar[i] = i;
		}
		return ar;
	}

	public static <T extends Comparable<T>> T max(Iterator<T> it){
		T max = null;
		while(it.hasNext()){
			T next = it.next();
			if(max == null || max.compareTo(next) == -1)
				max = next;
		}
		return max;
	}


	public static void main(String[] args){
	    ArrayList<Integer> ar = new ArrayList<Integer>();
		ar.add(1);
		ar.add(2);
		ar.add(3);
		ar.add(4);
		ar.add(5);
		System.out.println(max(ar.iterator()));
	}
} public class Couple<T, U> implements Cloneable {

	/**
	 * First element of the couple.
	 */
	public T first;

	/**
	 * Second element of the couple.
	 */
	public U second;

	/**
	 * Create a new empty couple
	 */
	public Couple() {
		first = null;
		second = null;
	}

	/**
	 * Create a new couple with {@link #first} set to f and {@link #second} set
	 * to s.
	 */
	public Couple(T f, U s) {
		first = f;
		second = s;
	}

	/**
	 * Create a new couple copy of c
	 */
	public Couple(Couple<T, U> c) {
		first = c.first;
		second = c.second;
	}

	public String toString() {
		StringBuilder s = new StringBuilder();
		s.append('(');
		s.append(first);
		s.append(',');
		s.append(second);
		s.append(')');
		return s.toString();
	}

	@SuppressWarnings("rawtypes")
	public boolean equals(Object o) {
		if (o instanceof Couple) {
			return first.equals(((Couple) o).first)
					&& second.equals(((Couple) o).second);
		}
		return false;
	}

	public int hashCode() {
		int i1 = (first == null) ? 0 : first.hashCode();
		int i2 = (second == null) ? 0 : second.hashCode();
		return i1 ^ i2;
	}

	@SuppressWarnings("unchecked")
	public Object clone() {
		try {
			return (Couple<T, U>) super.clone();

		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * @return the couple where second and first are switched.
	 */
	public Couple<U, T> reverse() {
		return new Couple<U, T>(second, first);
	}

	public static void main(String[] args) {
		int[] a = { 1, 2 };
		int[] b = { 2, 3 };
		Couple<int[], int[]> c = new Couple<int[], int[]>(a, b);

		System.out.println(c);
		System.out.println(c.clone());
	}
} public interface Foncteur<T, U> {

	/**
	 * Apply this function to o and return the result.
	 * 
	 * @param o
	 * @return this function applied to o.
	 */
	public U apply(T o);
} public class MultiIterator<T> implements Iterator<T> {

	/**
	 * List of iterators iterating collections
	 */
	private ArrayList<Iterator<T>> its;

	/**
	 * Index of the iterator currently iterating in the list its.
	 */
	private int icol;

	/**
	 * Create a new iterator over every collection of the list collections.
	 * 
	 * @param collections
	 */
	public MultiIterator(ArrayList<Collection<T>> collections) {
		its = new ArrayList<Iterator<T>>();
		for (Collection<T> col : collections)
			its.add(col.iterator());
		icol = (collections.size() > 0) ? 0 : Integer.MIN_VALUE;
	}

	/**
	 * Return an iterator over every collection iterated by the iterators in the
	 * list iterators.
	 * 
	 * @param iterators
	 */
	@SafeVarargs
	public MultiIterator(Iterator<T>... iterators) {
		its = new ArrayList<Iterator<T>>();
		for (Iterator<T> it : iterators)
			its.add(it);
		icol = (iterators.length > 0) ? 0 : Integer.MIN_VALUE;
	}

	@Override
	public boolean hasNext() {
		if (icol == Integer.MIN_VALUE)
			return false;
		else {
			Iterator<T> it;
			if (icol == -1)
				icol++;
			while (icol < its.size()) {
				it = its.get(icol);
				if (it.hasNext())
					return true;
				icol++;
			}
			return false;
		}
	}

	@Override
	public T next() {
		if (icol == Integer.MIN_VALUE)
			return null;
		else {
			Iterator<T> it;
			while (icol < its.size()) {
				it = its.get(icol);
				if (it.hasNext())
					return it.next();
				icol++;
			}
			return null;
		}
	}

	@Override
	public void remove() {

	}

} public interface Parametable {

	public abstract void defineParam(String s, Object obj);

	public abstract boolean containsParam(String s);

	public abstract Object getParam(String s);

	public abstract Integer getParamInteger(String s);

	public abstract Double getParamDouble(String s);

	public abstract Long getParamLong(String s);

	public abstract String getParamString(String s);

	public abstract Boolean getParamBoolean(String s);

	public abstract void clearParams();

	public abstract void copyParams(Parametable a);

	public abstract Set<String> getParamsNames();
} public class PartialIterator<T> implements Iterator<T> {

	/**
	 * Classic iterator over the iterated collection.
	 */
	private Iterator<T> it;

	/**
	 * Predicate deciding which elements have to be iterated and which have to
	 * be ignored.
	 */
	private Foncteur<T, Boolean> isIterable;

	/**
	 * Next element to be returned.
	 */
	private T next;

	/**
	 * Create a new PartialIterator over the collection col, using isIterable
	 * predicate to decide which elements have to be iterated and which have to
	 * be ignored.
	 * 
	 * @param col
	 * @param isIterable
	 */
	public PartialIterator(Collection<T> col, Foncteur<T, Boolean> isIterable) {
		this.isIterable = isIterable;
		it = col.iterator();
		next = null;
		while (it.hasNext()) {
			T m = it.next();
			if (isIterable.apply(m)) {
				next = m;
				break;
			}
		}
	}

	@Override
	public boolean hasNext() {
		return next != null;
	}

	@Override
	public T next() {
		if (next == null)
			throw new NoSuchElementException();

		T n = next;
		next = null;
		while (it.hasNext()) {
			T m = it.next();
			if (isIterable.apply(m)) {
				next = m;
				break;
			}
		}
		return n;
	}

	@Override
	public void remove() {
	}

} public class Triplet<T, U, V> {
	public T first;
	public U second;
	public V third;

	public Triplet(){
	}
	
	public Triplet(T f, U s, V t) {
		first = f;
		second = s;
		third = t;
	}

	public String toString() {
		StringBuilder s = new StringBuilder();
		s.append('(');
		s.append(first);
		s.append(',');
		s.append(second);
		s.append(',');
		s.append(third);
		s.append(')');
		return s.toString();
	}

	public int hashCode() {
		int i1 = (first == null) ? 0 : first.hashCode();
		int i2 = (second == null) ? 0 : second.hashCode();
		int i3 = (third == null) ? 0 : third.hashCode();

		return (i1 ^ i2) ^ i3;
	}

	@SuppressWarnings("unchecked")
	public boolean equals(Object o) {
		if (o instanceof Triplet) {
			Triplet<T, U, V> t = (Triplet<T, U, V>) o;
			return (first == null && t.first == null)
					|| (first != null && first.equals(t.first))
					&& (second == null && t.second == null)
					|| (second != null && second.equals(t.second))
					&& (third == null && t.third == null)
					|| (third != null && third.equals(t.third));
		}
		return false;
	}

	@SuppressWarnings("unchecked")
	public Object clone() {
		try {
			return (Triplet<T, U, V>) super.clone();

		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}
}
import graphTheory.graphDrawer.symbols.ArcArrowSymbol;
import graphTheory.graphDrawer.symbols.ArcCircleMiddleDistanceSymbol;
import graphTheory.graphDrawer.symbols.ArcCircleStartAngleSymbol;
import graphTheory.graphDrawer.symbols.ArcLineSymbol;
import graphTheory.graphDrawer.symbols.ArcSymbol;
import graphTheory.graphDrawer.symbols.NodeCircleSymbol;
import graphTheory.graphDrawer.symbols.NodeSquareSymbol;
import graphTheory.graphDrawer.symbols.NodeSymbol;
import graphTheory.utils.Collections2;
import graphTheory.utils.Couple;
import graphTheory.utils.Foncteur;
import graphTheory.utils.MultiIterator;
import graphTheory.utils.Parametable;
import graphTheory.utils.PartialIterator;
import graphTheory.utils.Triplet;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
			if (read.contains(n))
				continue;
			h = getConnectedComponent(n);
			read.addAll(h);
			l.add(h);
		}
		return l;
	}

	/**
	 * @param n
	 * @return The connected component of this containing the node n, null if n
	 *         do not belong to this
	 */
	public ArrayList<Integer> getConnectedComponent(Integer n) {
		LinkedList<Integer> l = new LinkedList<Integer>();
		HashSet<Integer> h = new HashSet<Integer>();
		l.add(n);
		Integer u = l.pop();
		h.add(u);
		Iterator<Arc> it = this.getAllNeighbourIterator(u);
		if (it == null)
			return null;

		do {
			while (it.hasNext())
				l.add(this.getNeighbourNode(u, it.next()));

			if (l.isEmpty())
				break;

			u = l.pop();
			if ((h.contains(u)))
				continue;
			h.add(u);
			it = this.getAllNeighbourIterator(u);

		} while (true);

		return new ArrayList<Integer>(h);
	}

	/**
	 * Return true if a path connecting n1 and n2 exists in this. This path can
	 * use only undirected edges.
	 * 
	 * @param n1
	 * @param n2
	 * @return true if a undirected path connecting n1 and n2 exists in this.
	 *         False if not or if n1 or n2 do not belong to this.
	 * @see #areConnectedByDirectedPath(Integer, Integer)
	 */
	public boolean areConnectedByUndirectedEdges(Integer n1, Integer n2) {
		return areConnected(n1, n2, true, false);
	}

	/**
	 * 
	 * Return true if a path connecting n1 and n2 exists in this. This path can
	 * use only directed edges.
	 * 
	 * @param n1
	 * @param n2
	 * @return true if a directed path from n1 to n2 exists in this. False if
	 *         not or if n1 or n2 do not belong to this.
	 */
	public boolean areConnectedByDirectedPath(Integer n1, Integer n2) {
		return areConnected(n1, n2, false, true);
	}

	/**
	 * Return true if a path connecting n1 and n2 exists in this. This path can
	 * use directed and undirected edges.
	 * 
	 * @param n1
	 * @param n2
	 * @return true if a path connecting n1 and n2 exists in this. False if not
	 *         or if n1 or n2 do not belong to this.
	 * @see #areConnectedByDirectedPath(Integer, Integer)
	 */
	public boolean areConnected(Integer n1, Integer n2) {
		return areConnected(n1, n2, true, true);
	}

	/**
	 * Return true if a path connecting n1 and n2 exists in this. This path can
	 * use directed edges if useDirected is true and undirected edges if use
	 * undirected is true.
	 * 
	 * @param n1
	 * @param n2
	 * @param useUndirected
	 * @param useDirected
	 * @return true if a path connecting n1 and n2 exists in this while
	 *         respecting useUndirected and useDirected. False if not or if n1
	 *         or n2 do not belong to this.
	 */
	private boolean areConnected(Integer n1, Integer n2, boolean useUndirected,
			boolean useDirected) {

		boolean contains1 = this.contains(n1);
		if (!contains1)
			return false;
		if ((n1 == n2 || n1.equals(n2)))
			return true;

		if (!useUndirected && !useDirected)
			return false;

		LinkedList<Integer> l = new LinkedList<Integer>();
		HashSet<Integer> h = new HashSet<Integer>();
		l.add(n1);
		Integer u, v;
		Iterator<Arc> it;
		while (!l.isEmpty()) {
			u = l.pop();
			if (h.contains(u))
				continue;

			h.add(u);
			it = new MultiIterator<Arc>(this.getOutputArcsIterator(u),