在C#中使用Krager算法求解最小割图

时间:2013-07-21 21:21:20

标签: c# algorithm graph-algorithm

   public class Graph
{
    public Graph()
    {
        Vertices = new Dictionary<int, List<int>>();
    }

    public Dictionary<int,List<int>> Vertices { get; set; }

    public void ApplyKrager()
    {
        var random = new Random();
        while (Vertices.Count > 2)
        {

            var randomIndex = random.Next(0,Vertices.Keys.Count);
            var firstVertex = Vertices.Keys.ElementAt(randomIndex);
            var secondVertex = Vertices[firstVertex].ElementAt(random.Next(0,Vertices[firstVertex].Count));
            if (Vertices.ContainsKey(secondVertex))
            {
                Console.WriteLine();
                Console.WriteLine("Merging " + firstVertex + " " + secondVertex);
                //Merge
                foreach (var edge in Vertices[secondVertex])
                {
                    if (!Vertices[firstVertex].Contains(edge))
                        Vertices[firstVertex].Add(edge);
                }

                //change all the occurences of the secondVertex to the first
                foreach (var vertex in Vertices)
                {
                    if (vertex.Value.Contains(secondVertex))
                    {
                        vertex.Value.Remove(secondVertex);
                        vertex.Value.Add(firstVertex);
                    }
                }
                //Remove Self Loops
                Vertices[firstVertex].RemoveAll(_ => _ == firstVertex);
                Vertices.Remove(secondVertex);
            }
            //Print();
        }

    }

    public void Print()
    {
        foreach (var v in Vertices)
        {
            Console.WriteLine("Vertex is : " + v.Key);
            Console.Write("Edges are ");
            foreach (var edge in v.Value)
            {
                Console.Write(edge + " ");
            }
            Console.WriteLine();
        }
    }
}

运行此代码的测试

    [Fact]
    public void CheckForMinimumCuts()
    {
          var input = File.ReadAllLines(@"input.txt");
        var directedEdges = new Dictionary<int, List<int>>();
        foreach (var line in input)
        {
            var adjacency = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            var vertex = Convert.ToInt32(adjacency[0]);
            var edges = new List<int>();
            for (int i = 1, j = 0; i < adjacency.Length; i++)
            {
                edges.Add(Convert.ToInt32(adjacency[i]));
            }

            directedEdges.Add(vertex, edges);
        }

        var cuts = new List<int>();
        for (int i = 0; i < 500; i++)
        {
            var graph = new Graph {Vertices = directedEdges};
            graph.ApplyKrager();
            foreach (var v in graph.Vertices)
            {
                cuts.Add(v.Value.Count);
            }
        }

        Console.WriteLine(cuts.Min());
    }

// input.txt中

1 3 4 2
2 1 4 3
3 1 2 4
4 5 3 2 1
5 4 8 6 7
6 8 7 5
7 5 8 6
8 5 7 6

expected result: 1
cut is [(4,5)]

上面的算法不会给出正确的输出,即使多次运行也会产生randmisation。

我对随机边缘的选择是否有所偏差?

我应该做cuts.Add(graph.Vertices.first()。count()而不是吗?

或者我的算法编码错误,因此无法正确输出?

注意:尝试将此问题标记为作业..无法找到标记。

2 个答案:

答案 0 :(得分:2)

随机收缩最小割算法要求您统一随机选择。您可以随机选择一个顶点,然后均匀地随机选择一个具有该顶点的边缘事件。

您可能还有一个我无法看到的实现错误,因为我不知道C#。如果你的算法在8顶点图上的500次迭代未能识别最小切割,我会感到惊讶。 new Random()每次都会生成一个具有相同种子的RNG吗?

答案 1 :(得分:0)

我认为你在块中犯了一个错误

//change all the occurences of the secondVertex to the first.              

if(!Vertices[firstVertex].Contains(edge))更改为while(!Vertices[firstVertex].Contains(edge)),否则更换只会发生一次。