同意您绝对应该删除自循环。还有一点我想补充的是,在你随机选择第一个顶点之后,你不必随机选择另一个节点,直到你有一个连接到第一个节点的节点,你可以简单地从连接到的节点中选择第一个顶点,因为您知道第一个选择的节点连接到多少个节点。所以在较小的范围内进行第二次随机选择。这只是有效地随机选择一条边(由两个节点/顶点确定)。我有一些实现 krager 算法的 c# 代码,你可以玩转。它不是最有效的代码(尤其是可以使用更高效的数据结构),因为我在 200 个节点图上对其进行了测试,对于 10000 次迭代,它需要大约 30 秒才能运行。
using System;
using System.Collections.Generic;
using System.Linq;
namespace MinCut
{
internal struct Graph
{
public int N { get; private set; }
public readonly List<int> Connections;
public Graph(int n) : this()
{
N = n;
Connections = new List<int>();
}
public override bool Equals(object obj)
{
return Equals((Graph)obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
private bool Equals(Graph g)
{
return N == g.N;
}
}
internal sealed class GraphContraction
{
public static void Run(IList<Graph> graphs, int i)
{
var liveGraphs = graphs.Count;
if (i >= liveGraphs)
{
throw new Exception("Wrong random index generation; index cannot be larger than the number of nodes");
}
var leftV = graphs[i];
var r = new Random();
var index = r.Next(0, leftV.Connections.Count);
var rightV = graphs.Where(x=>x.N == leftV.Connections[index]).Single();
foreach (var v in graphs.Where(x => !x.Equals(leftV) && x.Connections.Contains(leftV.N)))
{
v.Connections.RemoveAll(x => x == leftV.N);
}
foreach (var c in leftV.Connections)
{
if (c != rightV.N)
{
rightV.Connections.Add(c);
int c1 = c;
graphs.Where(x=> x.N == c1).First().Connections.Add(rightV.N);
}
}
graphs.Remove(leftV);
}
}
}