/// <summary>
 /// returns true if graph contains given vertice false otherwise
 /// </summary>
 /// <param name="v"></param>
 /// <returns></returns>
 public bool Contains(Vertice v)
 {
     foreach (Vertice vert in Vertices)
         if (vert.Equals(v))
             return true;
     return false;
 }
        /// <summary>
        /// add edge to our graph
        /// </summary>
        /// <param name="e"></param>
        public void AddEdge(Edge e)
        {
            if (this.Contains(e))
                return;

            Vertice v1 = new Vertice(e.v1);
            Vertice v2 = new Vertice(e.v2);

            if(!this.Contains(v1))
                this.Vertices.Add(v1);
            if(!this.Contains(v2))
                this.Vertices.Add(v2);

            this.Edges.Add(e);
        }
        /// <summary>
        /// add vertice to our graph
        /// </summary>
        /// <param name="e"></param>
        public void AddVertice(Vertice v)
        {
            if (this.Contains(v))
                return;

            this.Vertices.Add(v);
        }
 /// <summary>
 /// returns sub graph neighbors vertices in super graph
 /// </summary>
 /// <param name="super"></param>
 /// <param name="sub"></param>
 /// <returns></returns>
 public static List<Vertice> GetVerticesNeighborhood(Graph super, Graph sub,Vertice subVertice)
 {
     List<Vertice> nhood = new List<Vertice>();
     foreach (Edge e in super.Edges)
             if (subVertice.index == e.v1 && !sub.Contains(e))
             {
                 nhood.Add(new Vertice(e.v2));
             }
             else if (subVertice.index == e.v2 && !sub.Contains(e))
             {
                 nhood.Add(new Vertice(e.v1));
             }
     return nhood;
 }
 private static int GetTentativeDistance(Graph graph, Vertice v1, Vertice v2)
 {
     if (v1 == v2)
         return 0;
     if (graph.Contains(new Edge(v1.index, v2.index)))
         return 1;
     return int.MaxValue;
 }
        private static Graph GetPairGraph(Graph graph, Vertice u, Vertice v)
        {
            List<List<Vertice>> paths = GetDijkstraShortestPaths(graph, u);
            List<Vertice> shortestPathUV = paths[v.index];

            Graph pairUV = new Graph();
            if (shortestPathUV != null)
            {
                foreach (Vertice current in shortestPathUV)
                {
                    pairUV.Vertices.Add(current);
                    foreach (Edge edge in graph.Edges)
                    {
                        if (edge.v1 == current.index || edge.v2 == current.index)
                        {
                            pairUV.AddEdge(edge);
                        }
                    }
                }
            }

            return pairUV;
        }
        //Dijkstra's shortest paths
        public static List<List<Vertice>> GetDijkstraShortestPaths(Graph graph, Vertice vSource)
        {
            int[] distances = new int[graph.Vertices.Count];
            bool[] visited = new bool[graph.Vertices.Count];
            visited[vSource.index] = true;

            foreach (Vertice vOuter in graph.Vertices)
                distances[vOuter.index] = GetTentativeDistance(graph, vOuter, vSource);

            while (true)
            {
                int iMin = GetMinimumUnvisitedIndex(distances, visited);
                visited[iMin] = true;

                foreach (Vertice vCurrent in graph.Vertices)
                {
                    if (visited[vCurrent.index] == false)
                    {
                        if (GetTentativeDistance(graph, graph.Vertices[iMin], vCurrent) == int.MaxValue)
                            continue;

                        distances[vCurrent.index] = Math.Min(distances[iMin] + GetTentativeDistance(graph, graph.Vertices[iMin], vCurrent), distances[vCurrent.index]);
                    }
                }

                bool finished = true;
                for (int i = 0; i < visited.Length; i++)
                {
                    if (visited[i] == false && distances[i] != int.MaxValue)
                    {
                        finished = false;
                        break;
                    }
                }
                if (finished)
                    break;
            }

            var shortestPaths = new List<List<Vertice>>();

            foreach (Vertice vCurrent in graph.Vertices)
            {
                Vertice vTemp = vCurrent;
                shortestPaths.Add(new List<Vertice>());
                shortestPaths[vCurrent.index].Insert(0, vCurrent);
                if (distances[vCurrent.index] == int.MaxValue)
                {
                    shortestPaths[vCurrent.index] = null;
                    continue;
                }
                if (vCurrent == vSource)
                {
                    shortestPaths[vCurrent.index].Add(vSource);
                    continue;
                }

                while (true)
                {
                    foreach (Edge eCurrent in graph.Edges)
                    {
                        if (eCurrent.v1 == vTemp.index && distances[eCurrent.v2] == distances[vTemp.index] - 1)
                        {
                            shortestPaths[vCurrent.index].Insert(0, graph.Vertices[eCurrent.v2]);
                            vTemp = graph.Vertices[eCurrent.v2];
                            break;
                        }
                        else if (eCurrent.v2 == vTemp.index && distances[eCurrent.v1] == distances[vTemp.index] - 1)
                        {
                            shortestPaths[vCurrent.index].Insert(0, graph.Vertices[eCurrent.v1]);
                            vTemp = graph.Vertices[eCurrent.v1];
                            break;
                        }
                    }
                    if (vTemp == vSource)
                    {
                        break;
                    }
                }
            }
            return shortestPaths;
        }
        public static int GetCollaterialDistanceAndPairGraph(Graph graph, Vertice u, Vertice v,  //Procedure 3.2
            ref Graph pair)
        {
            Graph collaterial = GetCollaterialGraph(graph, new Edge(u.index, v.index));
            List<List<Vertice>> shortestPathsU = GetDijkstraShortestPaths(collaterial, u);
            List<List<Vertice>> shortestPathsV = GetDijkstraShortestPaths(collaterial, v);
            pair = GetPairGraph(graph, u, v);

            int collaterialUVDistance = shortestPathsU[graph.Vertices.IndexOf(v)].Count - 1;
            return collaterialUVDistance;
        }