用于在图中找到Min Cuts的随机收缩算法

时间:2012-04-07 14:17:39

标签: algorithm random graph

好的,所以这是我在图表中找到切割的算法(我不是在谈论最小切割)

假设我们获得了非有向图的邻接列表。

  1. 选择图表上的任何顶点(让它用数字表示)
  2. 选择图表上的任何其他顶点(随机)。 (用x表示)
  3. 如果两个顶点之间有边,则从图中删除该边。并将x所连接的所有顶点转移到pivot上。 (如果没有,请返回步骤2.
  4. 如果任何其他顶点连接到x,则更改邻接列表,以便现在x被pivot替换。即它们与Pivot相连。
  5. 如果顶点数大于2(返回步骤2)
  6. 如果等于2.只计算2个点中任一个的邻接列表中存在的顶点数。这将提供剪切
  7. 我的问题是,这个算法是否正确?

3 个答案:

答案 0 :(得分:1)

对于无向图的Krager Min-Cut算法,这是一个很好的解释。

我想你可能错过了一个细节。或许我只是误读了你的描述。

您想删除所有自循环。

例如,在移除顶点并运行算法后,顶点A现在可能具有从顶点A到顶点A的边。这称为自循环。并且它们在收缩两个顶点的过程中经常生成。作为第一步,您可以简单地检查整个图形以进行自循环,尽管有一些更复杂的方法。

这有意义吗?

答案 1 :(得分:1)

我只会改变你的随机化。

选择第一个顶点后,从邻接列表中选择另一个顶点。现在您确定两个顶点之间有边缘。下一步是从附属列表中找到顶点。

答案 2 :(得分:-1)

同意你绝对应该删除自我循环。 另外我要添加的另一点是,在你随机选择第一个顶点之后,你不必随意选择另一个节点,直到你有一个连接到第一个节点,你可以简单地选择连接到第一个节点的节点。第一个顶点,因为你知道有多少个节点是第一个连接的节点。所以在较小范围内进行第二次随机选择。这只是有效地随机选择边缘(由两个节点/顶点确定)。我有一些c#代码实现你可以玩的krager算法。它不是最有效的代码(特别是可以使用更高效的数据结构),因为我在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);
    }
}

}