// Path: src/main/java/org/chocosolver/graphsolver/variables/UndirectedGraphVar.java
// public class UndirectedGraphVar extends GraphVar<UndirectedGraph> {
// 
// 	//////////////////////////////// GRAPH PART /////////////////////////////////////////
// 
// 	//***********************************************************************************
// 	// CONSTRUCTORS
// 	//***********************************************************************************
// 
// 	/**
// 	 * Creates a graph variable
// 	 *
// 	 * @param name
// 	 * @param solver
// 	 * @param LB
// 	 * @param UB
// 	 */
// 	public UndirectedGraphVar(String name, Model solver, UndirectedGraph LB, UndirectedGraph UB) {
// 		super(name, solver, LB, UB);
// 	}
// 
// 	//***********************************************************************************
// 	// METHODS
// 	//***********************************************************************************
// 
// 	@Override
// 	public boolean removeArc(int x, int y, ICause cause) throws ContradictionException {
// 		assert cause != null;
// 		if (LB.edgeExists(x, y)) {
// 			this.contradiction(cause, "remove mandatory arc");
// 			return false;
// 		}
// 		if (UB.removeEdge(x, y)) {
// 			if (reactOnModification) {
// 				delta.add(x, GraphDelta.AR_TAIL, cause);
// 				delta.add(y, GraphDelta.AR_HEAD, cause);
// 			}
// 			GraphEventType e = GraphEventType.REMOVE_ARC;
// 			notifyPropagators(e, cause);
// 			return true;
// 		}
// 		return false;
// 	}
// 
// 	@Override
// 	public boolean enforceArc(int x, int y, ICause cause) throws ContradictionException {
// 		assert cause != null;
// 		enforceNode(x, cause);
// 		enforceNode(y, cause);
// 		if (UB.edgeExists(x, y)) {
// 			if (LB.addEdge(x, y)) {
// 				if (reactOnModification) {
// 					delta.add(x, GraphDelta.AE_TAIL, cause);
// 					delta.add(y, GraphDelta.AE_HEAD, cause);
// 				}
// 				GraphEventType e = GraphEventType.ADD_ARC;
// 				notifyPropagators(e, cause);
// 				return true;
// 			}
// 			return false;
// 		}
// 		this.contradiction(cause, "enforce arc which is not in the domain");
// 		return false;
// 	}
// 
// 	/**
// 	 * Get the set of neighbors of vertex 'idx' in the lower bound graph
// 	 * (mandatory incident edges)
// 	 *
// 	 * @param idx a vertex
// 	 * @return The set of neighbors of 'idx' in LB
// 	 */
// 	public ISet getMandNeighOf(int idx) {
// 		return getMandSuccOrNeighOf(idx);
// 	}
// 
// 	/**
// 	 * Get the set of neighbors of vertex 'idx' in the upper bound graph
// 	 * (potential incident edges)
// 	 *
// 	 * @param idx a vertex
// 	 * @return The set of neighbors of 'idx' in UB
// 	 */
// 	public ISet getPotNeighOf(int idx) {
// 		return getPotSuccOrNeighOf(idx);
// 	}
// 
// 	@Override
// 	public boolean isDirected() {
// 		return false;
// 	}
// }


import gnu.trove.list.array.TIntArrayList;
import org.chocosolver.graphsolver.variables.UndirectedGraphVar;
import org.chocosolver.util.objects.setDataStructures.ISet;
import org.chocosolver.util.objects.setDataStructures.SetFactory;
import java.util.BitSet;
package org.chocosolver.graphsolver.util;



/**
 * @author Jean-Guillaume FAGES (cosling)
 * @since 18/01/2019.
 */
public class UGVarConnectivityHelper {

	// input data
	private final UndirectedGraphVar g;
	private final int n;

	// internal variable for graph exploration
	private final int[] fifo;

	// internal variables for Articulation Points and Bridge detection
	private TIntArrayList bridgeFrom, bridgeTo;
	private BitSet hasMandInSubtree, visited;
	private ISet articulationPoints;
	private int[] parent, time, minT;
	private int[] timer = new int[1];

// Path: src/main/java/org/chocosolver/graphsolver/variables/UndirectedGraphVar.java
// public class UndirectedGraphVar extends GraphVar<UndirectedGraph> {
// 
// 	//////////////////////////////// GRAPH PART /////////////////////////////////////////
// 
// 	//***********************************************************************************
// 	// CONSTRUCTORS
// 	//***********************************************************************************
// 
// 	/**
// 	 * Creates a graph variable
// 	 *
// 	 * @param name
// 	 * @param solver
// 	 * @param LB
// 	 * @param UB
// 	 */
// 	public UndirectedGraphVar(String name, Model solver, UndirectedGraph LB, UndirectedGraph UB) {
// 		super(name, solver, LB, UB);
// 	}
// 
// 	//***********************************************************************************
// 	// METHODS
// 	//***********************************************************************************
// 
// 	@Override
// 	public boolean removeArc(int x, int y, ICause cause) throws ContradictionException {
// 		assert cause != null;
// 		if (LB.edgeExists(x, y)) {
// 			this.contradiction(cause, "remove mandatory arc");
// 			return false;
// 		}
// 		if (UB.removeEdge(x, y)) {
// 			if (reactOnModification) {
// 				delta.add(x, GraphDelta.AR_TAIL, cause);
// 				delta.add(y, GraphDelta.AR_HEAD, cause);
// 			}
// 			GraphEventType e = GraphEventType.REMOVE_ARC;
// 			notifyPropagators(e, cause);
// 			return true;
// 		}
// 		return false;
// 	}
// 
// 	@Override
// 	public boolean enforceArc(int x, int y, ICause cause) throws ContradictionException {
// 		assert cause != null;
// 		enforceNode(x, cause);
// 		enforceNode(y, cause);
// 		if (UB.edgeExists(x, y)) {
// 			if (LB.addEdge(x, y)) {
// 				if (reactOnModification) {
// 					delta.add(x, GraphDelta.AE_TAIL, cause);
// 					delta.add(y, GraphDelta.AE_HEAD, cause);
// 				}
// 				GraphEventType e = GraphEventType.ADD_ARC;
// 				notifyPropagators(e, cause);
// 				return true;
// 			}
// 			return false;
// 		}
// 		this.contradiction(cause, "enforce arc which is not in the domain");
// 		return false;
// 	}
// 
// 	/**
// 	 * Get the set of neighbors of vertex 'idx' in the lower bound graph
// 	 * (mandatory incident edges)
// 	 *
// 	 * @param idx a vertex
// 	 * @return The set of neighbors of 'idx' in LB
// 	 */
// 	public ISet getMandNeighOf(int idx) {
// 		return getMandSuccOrNeighOf(idx);
// 	}
// 
// 	/**
// 	 * Get the set of neighbors of vertex 'idx' in the upper bound graph
// 	 * (potential incident edges)
// 	 *
// 	 * @param idx a vertex
// 	 * @return The set of neighbors of 'idx' in UB
// 	 */
// 	public ISet getPotNeighOf(int idx) {
// 		return getPotSuccOrNeighOf(idx);
// 	}
// 
// 	@Override
// 	public boolean isDirected() {
// 		return false;
// 	}
// }


// Path: src/main/java/org/chocosolver/graphsolver/util/UGVarConnectivityHelper.java
import gnu.trove.list.array.TIntArrayList;
import org.chocosolver.graphsolver.variables.UndirectedGraphVar;
import org.chocosolver.util.objects.setDataStructures.ISet;
import org.chocosolver.util.objects.setDataStructures.SetFactory;
import java.util.BitSet;

package org.chocosolver.graphsolver.util;



/**
 * @author Jean-Guillaume FAGES (cosling)
 * @since 18/01/2019.
 */
public class UGVarConnectivityHelper {

	// input data
	private final UndirectedGraphVar g;
	private final int n;

	// internal variable for graph exploration
	private final int[] fifo;

	// internal variables for Articulation Points and Bridge detection
	private TIntArrayList bridgeFrom, bridgeTo;
	private BitSet hasMandInSubtree, visited;
	private ISet articulationPoints;
	private int[] parent, time, minT;
	private int[] timer = new int[1];

	public UGVarConnectivityHelper(UndirectedGraphVar g){