布尔变量自动改变其值

Boolean variable is automatically changing its value

本文关键字:改变 变量 布尔      更新时间:2023-10-16

这个问题来自SPOJ。我被要求找出这个图是否是双部的。我用BFS来找它。这里的问题是在//PROBLEM COMING HERE节下的while循环中(请参阅下面的代码以查找此语句)

问题描述:

我想在0和1之间切换。所以我选择了一个叫做flagbool值,并用0初始化它。现在,每次迭代我都要切换它的值。所以我用了flag = !flag。然而,由于某些未知的原因,在执行语句flag = ! flag之前,标志值在第一次迭代之后自动切换。因此,很多问题随之而来。

//BUG LIFE
#include <cstdio>
#include <vector>
#include <queue>
#define DEFAULT 2
using namespace std;
int main()
{
    int t,n,e;
    bool eflag;
    //freopen("input.txt", "r", stdin);
    //Taking the Testcase
    scanf("%d",&t);
    //Iterating each Testcase
    for(int itr=1; itr<=t; itr++)
    {
        //n is the number of nodes in the graph and e is the no of edges.
        scanf("%d %d",&n,&e);
        //eflag is exit flag in short. this is used to early exit to save time if we already found out that the given graph isn't bi-partite.
        //Assuming the graph is bi-partite hence eflag = false meaning no exit is required yet.
        eflag = false;
        //Graph data structure vector 2D Array
        vector < vector < int > > graph(n+1);
        //Taking edges as input and adding in the graph
        for(int i = 1; i <=e; i++)
        {
            int v1,v2;
            scanf("%d %d",&v1,&v2);
            graph[v1].push_back(v2);
            graph[v2].push_back(v1);
        }
        //Check the graph is bi-partite or not
        //vis is an array which will hold whether a node has been explored or not. label is an array which segregates all the nodes in two groups 0 or 1. 
        bool vis[n+1]; int label[n+1];
        //Initialising vis and label.
        for(int i=1; i<=n; i++)
        {
            vis[i] = 0;
            //DEFALUT VALUE IS 2. This is to tell that label of the node i hasn't been given yet or in otherwords, it's not be put in a group yet.
            label[i] = DEFAULT;
        }
        //Taking nodes one by one and doing a BFS on it.
        //LOGIC Here is: Take a node assign it a label 0 and add all the children of it in the queue and give them label 1. Now explore all children and give their children label 0. So like this, we alternate between labels. 
//Now if we see that a node already has a label apart from 2 and a children is trying to label it with something different label it will mean that specific node is involved in both the groups. Hence we will set the eflag as true.
        for(int i=1; i<=n && !eflag; i++)
        {
            if(!graph[i].empty() && !vis[i])
            {
                //Initialising the queue and adding the first node which has children.
                queue <int> q;
                q.push(i); bool flag;
                //PROBLEM COMING HERE
                //Assigning the label for this node as 0. meaning group 0
                label[i] = 0; flag = false;
                //BFS Starts
                while(!q.empty() && !eflag)
                {
                    int x = q.front();  q.pop();
                    printf("%d **n",flag);
                    //The children of this node needs to have different label than parent. Hence flag = !flag
                    flag = !flag;
                    printf("%d %dn",x,flag);
                    if(vis[x]) continue;
                    vis[x] = 1;
                    //Exploring the children and assigning them labels
                    for(vector <int>::iterator it = graph[x].begin(); it != graph[x].end(); it++)
                    {
                        //If the children doesn't have a default label and the label which it has is different than the one the parent is trying to put then it means that this child belongs to both the groups 0 and 1. So exit.
                        if(label[*it] != DEFAULT && label[*it] != flag)
                        {
                            printf("%d %d %d %dn",x,*it,label[*it],flag);
                            eflag = true;
                            break;
                        }
                        else
                        {
                            label[*it] = flag;
                        }
                    }
                    printf("asd %d **n",flag);
                }
                //PROBLEM ENDS HERE
            }
        }
        if(eflag == false)
            printf("Scenario #%d:nNo suspicious bugs found!n",itr);
        else
            printf("Scenario #%d:nSuspicious bugs found!n",itr);
    }
    return 0;
}
输出:

0 **
1 1 
asd 1 ** 
0 ** 
2 1 
2 1 0 1 
asd 1 ** 
Scenario #1: 
Suspicious bugs found! 

示例输入:

1
3 3
1 2
2 3
1 3

你在评论中的假设:

在输出asd 1**之后,它应该再次输出1**,因为flag = !Flag还没有被执行。但是它显示0 **

是错误的。(不是假设flag = ! flag没有被执行,这是正确的。)

在下面的代码片段中,我删除了大部分不相关的代码(不用谢)。让我们命名一些循环:

for(int i=1; i<=n && !eflag; i++) // outer loop
{
    // ..
        queue <int> q;
        q.push(i); bool flag;
        label[i] = 0; flag = false; // (1)
        while(!q.empty() && !eflag) // inner loop
        {
            int x = q.front();  q.pop();
            printf("%d **n",flag); // (2)
            flag = !flag;
            printf("%d %dn",x,flag);
            // ...
            printf("asd %d **n",flag); // (3)
        }
    // ...
}

只能将一个元素压入q。这是外环的顶部。你总是在内循环的顶部弹出它。只有当队列不为空时,内循环条件才为真。因此,对于每个外部循环,内部循环总是最多运行一次。因为内循环不会重复超过一次,所以在内循环(3)结束时打印asd 1**后,总是跳转到外循环的开始。在外循环(1)的顶部,分配flag = false。因此,无论flag在(3)处的值是多少,它在(2)处的值始终是false

正如你所看到的,变量没有"自动"改变,也没有因为"未知的原因"改变。它在变化,因为你把它赋值到(1)