public UndirectedGraph <T> Add(UndirectedEdge <T> edge) { _edges.Add(edge); foreach (var vertex in edge.Vertexs()) { _vertexs.Add(vertex); } return(this); }
/// <summary> /// 假设G=(V,E)为一无向连通网,其中,V为网中顶点的集合,E为网中边的集合。 /// 设置两个新的集合U和T,其中,U为G的最小生成树的顶点的集合,T为G的最小生成树的边的集合。 /// 普里姆算法的思想是:令集合U的初值为U={u1}(假设构造最小生成树时从顶点u1开始),集合T的初值为T={}。 /// 从所有的顶点u∈U和顶点v∈V-U的带权边中选出具有最小权值的边(u,v), /// 将顶点v加入集合U中,将边(u,v)加入集合T中。如此不断地重复直到U=V时,最小生成树构造完毕。 /// 此时,集合U中存放着最小生成树的所有顶点,集合T中存放着最小生成树的所有边。 /// </summary> /// <returns></returns> public List <UndirectedEdge <T> > PrimMinCostSpanTree(T begin_vertex) { if (!_vertexs.Contains(begin_vertex)) { throw new InvalidOperationException("begin_vertex is not in Graph"); } var ret = new List <UndirectedEdge <T> >(); var selected_set = new HashSet <T>(); var unselected_set = new HashSet <T>(); selected_set.Add(begin_vertex); foreach (var vertex in _vertexs) { if (!vertex.Equals(begin_vertex)) { unselected_set.Add(vertex); } } while (unselected_set.Count > 0) { T vertex_unsel = default(T); UndirectedEdge <T> edge_sel = null; var min_cost = int.MaxValue; foreach (var sel_item in selected_set) { foreach (var unsel_item in unselected_set) { foreach (var edge in _edges) { if (edge.ComposedWith(sel_item, unsel_item) && edge.Weight < min_cost) { vertex_unsel = unsel_item; min_cost = edge.Weight; edge_sel = edge; } } } } if (vertex_unsel != null && vertex_unsel.Equals(default(T))) { continue; } selected_set.Add(vertex_unsel); unselected_set.Remove(vertex_unsel); ret.Add(edge_sel); } return(ret); }
/// <summary> /// 图是否存在环 /// 1.求出图中所有顶点的度, /// 2.删除图中所有度小于等于1的顶点以及与该顶点相关的边,把与这些边相关的顶点的度减一 /// 3.如果还有度小于等于1的顶点重复步骤2 /// 4.最后如果还存在未被删除的顶点,则表示有环;否则没有环 /// </summary> /// <returns></returns> public bool HasLoop() { var dic = _vertexs.ToDictionary(v => v, v => 0); // vertex-degree var edges = new HashSet <UndirectedEdge <T> >(_edges); foreach (var edge in edges) // init degree of vertexs { foreach (var v in edge.Vertexs()) { dic[v]++; } } // delete all vertexs satified degree==0 var filtered_dic = dic.Where(item => item.Value > 0).ToDictionary(item => item.Key, item => item.Value); var to_do_item = GetOneDegreeItem(filtered_dic); // get one vertex which degree == 1 while (!to_do_item.Equals(default(KeyValuePair <T, int>))) { UndirectedEdge <T> to_del_edge = null; foreach (var edge in edges) { if (edge.Contain(to_do_item.Key)) { to_del_edge = edge; filtered_dic[edge.GetAdjoinVertex(to_do_item.Key)]--; break; } } filtered_dic.Remove(to_do_item.Key); edges.Remove(to_del_edge); to_do_item = GetOneDegreeItem(filtered_dic); } return(!(filtered_dic.Count == 0 || filtered_dic.All(item => item.Value == 0))); }