【问题标题】:getting error when return value but correct ans when pass by reference返回值时出错,但通过引用传递时正确
【发布时间】:2020-02-08 07:05:26
【问题描述】:

有 n 个孩子,每个孩子都在读一本独特的书。在任何一天结束时,第 i 个孩子会将他的书交给第 pi 个孩子(如果 i=pi,孩子会将他的书交给自己)。保证 pi 的所有值都是从 1 到 n 的不同整数(即 p 是一个排列)。序列 p 每天都不会改变,它是固定的。

例如,如果 n=6 和 p=[4,6,1,3,5,2],那么在第一天结束时,第 1 个孩子的书将属于第 4 个孩子,第 2 个孩子将属于第 6 个孩子,依此类推。在第二天结束时,第 1 孩子的书将属于第 3 孩子,第 2 孩子将属于第 2 孩子,依此类推。

你的任务是确定从 1 到 n 的每一个 i,第 i 个孩子的书第一次归还给他的天数。

考虑以下示例:p=[5,1,2,4,3]。第一个孩子的书将传递给以下孩子:

在第 1 天之后,它将属于第 5 个孩子, 第二天之后它会属于第三个孩子, 第 3 天之后,它将属于第 2 个孩子, 第 4 天之后,它将属于第 1 个孩子。 所以第四天之后,第一个孩子的书就会归还给它的主人。老四的书会在整整一天后第一次回到他的身边。

你必须回答 q 个独立的查询

使用的方法
不相交集
如果 1 给 4 则找到 1 和 4 的父级。如果父级不同,则执行 1 和 4 的联合,否则移动到下一对
最后 ans 是它所属集合的大小

例如-
1
6
4 6 2 1 5 3

//在findparent中通过引用传递p时给出正确答案的代码

#include<bits/stdc++.h>
using namespace std;

void findparent(int num,vector<int> s,int &p)
{
    if(s[num]<0)
    {
        p=num;
        return;
    }
    else
    {
        findparent(s[num],s,p);
    }
}

int main()
{
    int q;
    cin>>q;

    while(q)
    {

        int n;
        cin>>n;
        vector<int> v(n+1,0);

        for(int i=1;i<=n;i++)
        {
            int x;
            cin>>x;
            v[i]=x;
        }
        vector<int> s(n+1,-1);

        for(int i=1;i<=n;i++)
        {
            int a=i;
            int b=v[i];
            int pa;
            findparent(a,s,pa);
            int pb;
            findparent(b,s,pb);
            if(pa!=pb)
            {
                //union(a,b);
                 if(s[pa]<=s[pb])//negative values being considered
                 {
                     s[pa]=s[pa]+s[pb];
                     s[pb]=pa;
                 }
                 else
                 {
                     s[pb]=s[pa]+s[pb];
                     s[pa]=pb;
                 }
            }
        }

        vector<int> ans(n+1);
        for(int i=1;i<=n;i++)
        {
            int p;
            findparent(i,s,p);
            ans[i]=-s[p];
            cout<<ans[i]<<" ";
        }
        cout<<endl;

        q--;
    }

    return 0;
}

//函数findparent返回值时给出错误答案的代码

#include<bits/stdc++.h>
using namespace std;

int findparent(int num,vector<int> s)
{
    if(s[num]<0)
    {
        return num;
    }
    else
    {
        findparent(s[num],s);
    }
}

int main()
{
    int q;
    cin>>q;

    while(q)
    {

        int n;
        cin>>n;
        vector<int> v(n+1,0);

        for(int i=1;i<=n;i++)
        {
            int x;
            cin>>x;
            v[i]=x;
        }
        vector<int> s(n+1,-1);

        for(int i=1;i<=n;i++)
        {
            int a=i;
            int b=v[i];
            int pa=findparent(a,s);
            int pb=findparent(b,s);
            if(pa!=pb)
            {
                //union(a,b);
                if(s[pa]<=s[pb])//negative values being considered
                {
                     s[pa]=s[pa]+s[pb];
                     s[pb]=pa;
                }
                else
                {
                    s[pb]=s[pa]+s[pb];
                    s[pa]=pb;
                }
            }
        }
        vector<int> ans(n+1);
        for(int i=1;i<=n;i++)
        {
            int p=findparent(i,s);
            ans[i]=-s[p];
            cout<<ans[i]<<" ";
        }
        cout<<endl;

        q--;
    }

    return 0;
}

【问题讨论】:

  • "当函数 findparent 返回值时" else 的情况下不是这样。你没有收到任何编译器警告吗?

标签: c++ disjoint-sets


【解决方案1】:

第二个版本表现出未定义的行为。如果您仔细观察,您会发现,您并不总是返回值。

int findparent(int num,vector<int> s)
{
    if(s[num]<0)
    {
        return num; // Here you return something
    }
    else
    {
        findparent(s[num],s); // Here you return nothing
    }
}

正确的是

int findparent(int num, vector<int> s)
{
    if(s[num]<0)
    {
        return num; // Here you return something
    }
    else
    {
        return findparent(s[num],s); // return the result of the recursive call
    }
}

您的编译器也应该对此发出警告,因此请打开所有警告并听取它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-13
    • 1970-01-01
    • 2014-07-12
    • 1970-01-01
    • 2012-03-30
    • 1970-01-01
    • 2016-02-07
    相关资源
    最近更新 更多