セルフループを確実に削除する必要があることに同意します。また、最初の頂点をランダムに選択した後、最初のノードに接続されているノードができるまで、別のノードをランダムに選択する必要はありません。接続されているノードから選択するだけです。最初に選択されたノードが接続するノードの数がわかっているため、最初の頂点。したがって、より狭い範囲内の2番目のランダムな選択。これは、事実上ランダムにエッジを選択することです(2つのノード/頂点によって決定されます)。私はあなたが遊ぶことができる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);
}
}
}