【问题标题】:Program works fine only for one test case - Debugging [closed]程序仅适用于一个测试用例 - 调试 [关闭]
【发布时间】:2016-09-09 16:22:26
【问题描述】:

我想知道我的图是否是二分图,我有几个测试用例。如果我运行多个测试用例,它就不能正常工作,它总是显示 Bipartite。我很难弄清楚。仅在一种情况下,它适用于任何图表。
这是我的代码。

#include <iostream>
#include <cstdio>
#include <stack>
#include <list>

using namespace std;

class Graph
{
    public:
        int V;
        list<int> *adj;
        Graph(int V);
        void addEdge(int v, int w);
};

Graph::Graph(int V)
{
    this->V = V;
    adj = new list<int>[V];
}

void Graph::addEdge(int v, int w)
{
    adj[v].push_back(w);
    adj[w].push_back(v);
}

class Bipartite
{
    private:
        bool isBipartite;
        bool *color;
        bool *marked;
        int *edgeTo;
        stack<int> cycle;
    public:
        Bipartite(Graph G)
        {
            isBipartite = true;
            color = new bool [G.V];
            marked = new bool [G.V];
            edgeTo = new int [G.V];
            for (int v = 0; v < G.V; v++)
            {
                if (!marked[v])
                {
                    color[v] = false;
                    dfs(G, v);
                }
            }

            delete color;
            delete marked;
            delete edgeTo;
        }

        void dfs(Graph G, int v)
        {
            marked[v] = true;
            list<int>::iterator w;
            for (w = G.adj[v].begin(); w != G.adj[v].end(); w++)
            {
                if (!cycle.empty())
                    return;
                if (!marked[*w])
                {
                    edgeTo[*w] = v;
                    color[*w] = !color[v];
                    dfs(G, *w);
                }
                else if (color[*w] == color[v])
                {
                    isBipartite = false;
                    cycle.push(*w);
                    for (int x = v; x != *w; x = edgeTo[x])
                    {
                        cycle.push(x);
                    }
                    cycle.push(*w);
                }
            }
        }

        bool isBi()
        {
            return isBipartite;
        }
};

void solve(int n,int **p){
    long long int x,y;
    Graph g(n);

    for(x=0;x<n;x++)
        for(y=0;y<n;y++)
        {
            if(p[x][y]==1)
                g.addEdge(x,y);
        }

    Bipartite b(g);
    if (b.isBi())
        cout<<"YES"<<endl;
    else
        cout<<"NO"<<endl;
}

int main()
{

    long long int i,j,t,x,m,y,a,b;
    int **p,n;

    cin>>t;

    for(i=0;i<t;i++)
    {
        cin>>n>>m;

        p=new int*[n]();
        for(x=0;x<n;x++)
        {
            p[x]=new int[n]();
        }

        for(j=0;j<m;j++)
        {
            cin>>a>>b;
            a=a-1;
            b=b-1;

            p[a][b]=1;
            p[b][a]=1;

        }

        for(x=0;x<n;x++)
        {
            for(y=0;y<n;y++)
            {
                if(x!=y)
                {
                    p[x][y]=1-p[x][y];
                }
            }
        }

        /*  for(x=0;x<n;x++)
        {
            for(y=0;y<n;y++)
                cout<<p[x][y]<<" ";
            cout<<"\n";
        }
        */

        solve(n,p);
    }
    return 0;
}

【问题讨论】:

    标签: c++ debugging c++11 graph bipartite


    【解决方案1】:

    您永远不会显式初始化 marked 的内容,或者更准确地说,它指向的数组的内容。

    您的构造函数中的循环读取marked 的元素以决定如何分配给color,但您从未初始化正在读取的marked 的元素。

    coloredgeTo 的类似参数。

    这意味着,虽然他们可能已经对第一种情况进行了预期的初始化,但很可能会使用在以后的情况下发生的任何值。

    【讨论】:

    • 显式初始化你的变量。
    • 为它们赋值。
    • 现在代码工作正常,但我的实际问题是:它没有通过所有测试用例。我的实际问题是:我想实际检查是否可以将我的图划分为两个 Cliques(完整子图)。我所做的是补充邻接矩阵并检查 Bipartite。但它不起作用,知道为什么吗?
    • 如果它没有通过所有的测试用例,那么它就不能“正常工作”。
    • 我上面提到的问题得到了解决,但实际问题是检查:“我是否可以将我的图划分为两个Cliques(完整子图)。我的方法:我所做的是补充邻接矩阵并检查二分”
    【解决方案2】:

    同样Bipartite(Graph G) 正在调用Graph 的默认复制构造函数。可能不是你想要的。

    改用Bipartite(const Graph &amp; G)(也在dfs 中)。

    不要在没有delete 的情况下使用new

    宁可使用vector&lt;vector&lt;int&gt;&gt; adj;,为什么还要使用list?并在构造函数中使用adj.resize(V); 重新初始化它。


    在您编辑有问题的代码后,当您使用new 分配数组时,您也应该将其作为数组删除,因此请使用delete[] color;

    或者完全停止使用 new/delete。同样,您可以使用std::vector&lt;bool&gt; color(G.V);,避免new/delete 的麻烦,并且默认情况下将所有值初始化为false

    在现代 C++ 中,使用 newdelete 的理由很少(更像是“无”)(除非您编写了一些低级库,或者您正在优化性能,并且您 知道你在做什么)。

    【讨论】:

    • 现在代码工作正常,但我的实际问题是:它没有通过所有测试用例。我的实际问题是:我想实际检查是否可以将我的图划分为两个 Cliques(完整子图)。我所做的是补充邻接矩阵并检查 Bipartite。但它不起作用,知道为什么吗?
    • @Born2Code 我不确定我是否得到任务描述。所以如果你有两个人,连接,那么答案是“是”? (每个形成他自己的城市=集团,他们之间的联系被忽略)那么你的邻接补将是空边集?我没有检查您的来源,它会回答为“bipartition = OK”吗?无论如何,我对图论有点生疏,无法确定您的想法是否正确,但看不出明显的问题(除了双分区必须处理分离的子图)。但是我懒得检查你的代码。
    • 检查这个:link 在第一种情况下,我可以将它们划分为两个城市,1 个在一个城市,2 &3 在另一个城市。 [因为 2 和 3 彼此认识] 在第二种情况下,我无法将它们分开,因为它们在所述条件下无法分开。 [好像我分开了,他们都不会互相认识] 第三种情况,我可以分成两组,1、2、3一组,4、5、6组另一组。因为他们都认识。
    • @Born2Code 乍一看还不错。继续寻找失败的测试用例和调试(也验证单个公民输入、无公民输入、完整图形输入等)。但是您发布的代码看起来很容易出现内存泄漏、单元化值等问题,因此它也可能由于代码中的错误而失败,而不仅仅是逻辑上的错误。还可以获得一些关于现代 C++/教程的好书,并继续检查它们。也许先做一些更简单的任务,当你确定它工作正常时,将其发布以供 codereview。或者在完成任务后的许多任务站点上,您可能会检查其他解决方案,尽管它们很少会推广优质资源。
    • 您可能想学习如何使用 valgrind,这将有助于处理那些未初始化的值。
    猜你喜欢
    • 2017-08-22
    • 2022-11-14
    • 1970-01-01
    • 2011-07-17
    • 2021-12-27
    • 1970-01-01
    • 2018-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多