Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何计算最小二部顶点覆盖?_C#_Graph Theory - Fatal编程技术网

C# 如何计算最小二部顶点覆盖?

C# 如何计算最小二部顶点覆盖?,c#,graph-theory,C#,Graph Theory,如何计算C#中的最小二部顶点覆盖?有这样做的代码片段吗 编辑:一般图的问题是NP完全问题,而二部图的问题是多项式时间可解的。我知道它在某种程度上与二部图中的最大匹配有关(根据Konig定理),但我无法正确理解该定理,以便能够将最大二部匹配的结果转换为顶点覆盖。可能最好继续,随机选择一个节点。对于每个节点,要么它进入顶点覆盖,要么它的所有邻居都进入(因为需要包括该边)。整个过程的最终结果将是一组顶点覆盖,然后选择最小的一个。不过,我不会坐在这里把它编码出来,因为如果我没记错的话,它是NP完全的。我

如何计算C#中的最小二部顶点覆盖?有这样做的代码片段吗


编辑:一般图的问题是NP完全问题,而二部图的问题是多项式时间可解的。我知道它在某种程度上与二部图中的最大匹配有关(根据Konig定理),但我无法正确理解该定理,以便能够将最大二部匹配的结果转换为顶点覆盖。

可能最好继续,随机选择一个节点。对于每个节点,要么它进入顶点覆盖,要么它的所有邻居都进入(因为需要包括该边)。整个过程的最终结果将是一组顶点覆盖,然后选择最小的一个。不过,我不会坐在这里把它编码出来,因为如果我没记错的话,它是NP完全的。

我可以理解:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class VertexCover
{
    static void Main(string[] args)
    {
        var v = new VertexCover();
        v.ParseInput();
        v.FindVertexCover();
        v.PrintResults();
    }

    private void PrintResults()
    {
        Console.WriteLine(String.Join(" ", VertexCoverResult.Select(x => x.ToString()).ToArray()));
    }

    private void FindVertexCover()
    {
        FindBipartiteMatching();

        var TreeSet = new HashSet<int>();
        foreach (var v in LeftVertices)
            if (Matching[v] < 0)
                DepthFirstSearch(TreeSet, v, false);

        VertexCoverResult = new HashSet<int>(LeftVertices.Except(TreeSet).Union(RightVertices.Intersect(TreeSet)));
    }

    private void DepthFirstSearch(HashSet<int> TreeSet, int v, bool left)
    {
        if (TreeSet.Contains(v))
            return;
        TreeSet.Add(v);
        if (left) {
            foreach (var u in Edges[v])
                if (u != Matching[v])
                    DepthFirstSearch(TreeSet, u, true);
        } else if (Matching[v] >= 0)
            DepthFirstSearch(TreeSet, Matching[v], false);

    }

    private void FindBipartiteMatching()
    {
        Bicolorate();
        Matching = Enumerable.Repeat(-1, VertexCount).ToArray();
        var cnt = 0;
        foreach (var i in LeftVertices) {
            var seen = new bool[VertexCount];
            if (BipartiteMatchingInternal(seen, i)) cnt++;
        }
    }

    private bool BipartiteMatchingInternal(bool[] seen, int u)
    {
        foreach (var v in Edges[u]) {
            if (seen[v]) continue;
            seen[v] = true;
            if (Matching[v] < 0 || BipartiteMatchingInternal(seen, Matching[v])) {
                Matching[u] = v;
                Matching[v] = u;
                return true;
            }
        }
        return false;
    }

    private void Bicolorate()
    {
        LeftVertices = new HashSet<int>();
        RightVertices = new HashSet<int>();

        var colors = new int[VertexCount];
        for (int i = 0; i < VertexCount; ++i)
            if (colors[i] == 0 && !BicolorateInternal(colors, i, 1))
                throw new InvalidOperationException("Graph is NOT bipartite.");
    }

    private bool BicolorateInternal(int[] colors, int i, int color)
    {
        if (colors[i] == 0) {
            if (color == 1) LeftVertices.Add(i);
            else RightVertices.Add(i);
            colors[i] = color;
        } else if (colors[i] != color)
            return false;
        else
            return true;
        foreach (var j in Edges[i])
            if (!BicolorateInternal(colors, j, 3 - color))
                return false;
        return true;
    }

    private int VertexCount;
    private HashSet<int>[] Edges;
    private HashSet<int> LeftVertices;
    private HashSet<int> RightVertices;
    private HashSet<int> VertexCoverResult;
    private int[] Matching;

    private void ReadIntegerPair(out int x, out int y)
    {
        var input = Console.ReadLine();
        var splitted = input.Split(new char[] { ' ' }, 2);
        x = int.Parse(splitted[0]);
        y = int.Parse(splitted[1]);
    }

    private void ParseInput()
    {
        int EdgeCount;
        ReadIntegerPair(out VertexCount, out EdgeCount);
        Edges = new HashSet<int>[VertexCount];
        for (int i = 0; i < Edges.Length; ++i)
            Edges[i] = new HashSet<int>();

        for (int i = 0; i < EdgeCount; i++) {
            int x, y;
            ReadIntegerPair(out x, out y);
            Edges[x].Add(y);
            Edges[y].Add(x);
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
等级转换
{
静态void Main(字符串[]参数)
{
var v=新的顶点覆盖();
v、 ParseInput();
v、 FindVertexCover();
v、 打印结果();
}
私有void打印结果()
{
Console.WriteLine(String.Join(“,VertexCoverResult.Select(x=>x.ToString()).ToArray());
}
私有无效FindVertexCover()
{
FindBipartiteMatching();
var TreeSet=newhashset();
foreach(左顶点中的var v)
if(匹配[v]<0)
深度优先搜索(TreeSet,v,false);
VertexCoverResult=新哈希集(LeftVertices.Exception(TreeSet).Union(RightVertices.Intersect(TreeSet));
}
私有void DepthFirstSearch(哈希集树集,int v,布尔左)
{
如果(树集包含(v))
返回;
树集。添加(v);
如果(左){
foreach(边中的变量u[v])
如果(u!=匹配[v])
深度优先搜索(TreeSet,u,true);
}else if(匹配[v]>=0)
深度优先搜索(树集,匹配[v],假);
}
私有void FindBipartiteMatching()
{
双色();
匹配=可枚举。重复(-1,VertexCount).ToArray();
var-cnt=0;
foreach(左顶点中的变量i){
var seen=新bool[垂直计数];
if(内部(见,i))cnt++;
}
}
私有布尔二分体匹配内部(布尔[]见,内部u)
{
foreach(边[u]中的var v){
如果(见[v])继续;
看见的,看见的;
if(匹配[v]<0 | |二部匹配内部(参见,匹配[v])){
匹配[u]=v;
匹配[v]=u;
返回true;
}
}
返回false;
}
私有双色
{
LeftVertices=新HashSet();
RightVertices=新哈希集();
var colors=新整数[VERTECOUNT];
对于(int i=0;i
正如您所看到的,这段代码在多项式时间内解决了这个问题


 private void DepthFirstSearch(HashSet TreeSet, int v, bool left)
    {
        if (TreeSet.Contains(v))
            return;
        TreeSet.Add(v);
        if (left) {
            foreach (var u in Edges[v])
                if (u != Matching[v])
                    DepthFirstSearch(TreeSet, u, true);
        } else if (Matching[v] >= 0)
            DepthFirstSearch(TreeSet, Matching[v], false);

    }

当<强>if(左)时将执行我正在计算它的值始终是false

最小顶点覆盖应该是NP完全的。二部可能只是图的一个属性。SteveR应该在某个地方咨询NP完全问题的近似解…我想要二部版本。我知道它与匹配有关(科尼格定理)。但我不知道如何将二部匹配的结果转换为最小顶点覆盖。我的错误是,我没有看到“二部”这个词。对于其他参与此解决方案的人来说,它非常接近,但它有一个基本的缺陷DepthFirstSearch在开始时传递了一个false,而它应该是true。