布尔变量自动更改其值

时间:2015-09-04 11:06:14

标签: c++ algorithm

此问题来自SPOJ。我被要求查看图表是否是Bi-partite。我正在使用BFS找到它。 这里的问题是//PROBLEM COMING HERE部分下的while循环(请参阅下面的代码以查找此声明。)

问题描述:

我想在0和1之间切换。所以我选择了一个名为bool的{​​{1}}值,并将其初始化为0.现在,每次迭代我想切换它的值。所以我使用了flag。但是,由于某些未知原因,在执行语句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 %d\n",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 %d\n",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 个答案:

答案 0 :(得分:1)

您在评论中的假设:

  

打印asd 1 **后,它应该再打印1 **因为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 %d\n",x,flag);
            // ...
            printf("asd %d **\n",flag); // (3)
        }
    // ...
}

您只需将一个元素推入q。这是外循环的顶部。你总是把它放在内循环的顶部。仅当队列不为空时,内部循环条件才为真。因此,内环总是每个外环最多运行一次。因为内部循环永远不会重复多次,所以在内循环(3)结束时打印asd 1**之后总是跳到外循环的开头。在外循环(1)的顶部,指定flag = false。因此,无论{(1}}在(3)处打印时的值是多少,它的值始终为flag(2)。

正如您所看到的,变量不是“自动”更改,也不是因为“未知原因”。它正在改变,因为你在(1)分配它。