嵌套 if v/s && 运算符

nested if v/s && operator

我正在用 C++ 编写代码来检查给定的无向图中是否存在循环。 我的代码是这样的:-

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

// Class for an undirected graph
class Graph
{
    
    // No. of vertices
    int V;

    // Pointer to an array
    // containing adjacency lists
    list<int> *adj;
    bool isCyclicUtil(int v, bool visited[], int parent);
public:

    // Constructor
    Graph(int V);

    // To add an edge to graph
    void addEdge(int v, int w);

    // Returns true if there is a cycle
    bool isCyclic();
};

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

void Graph::addEdge(int v, int w)
{
    
    // Add w to v’s list.
    adj[v].push_back(w);

    // Add v to w’s list.
    adj[w].push_back(v);
}

// A recursive function that
// uses visited[] and parent to detect
// cycle in subgraph reachable
// from vertex v.
bool Graph::isCyclicUtil(int v, bool visited[], int parent)
{
    
    // Mark the current node as visited
    visited[v] = true;

    // Recur for all the vertices
    // adjacent to this vertex
    for(int i:adj[v])
    {
        
        // If an adjacent vertex is not visited,
        //then recur for that adjacent
        
        
//      if ((!visited[i])&&(isCyclicUtil(i, visited, v)))                //        1st block
//      {
//          return true;
//      }
      
        if (!visited[i]) {                                          //         2nd block
            if (isCyclicUtil(i, visited, v)) {
                return true;
            }
        }

        // If an adjacent vertex is visited and
        // is not parent of current vertex,
        // then there exists a cycle in the graph.
        else if (i != parent)
        return true;
    }
    return false;
}

// Returns true if the graph contains
// a cycle, else false.
bool Graph::isCyclic()
{
    
    // Mark all the vertices as not
    // visited and not part of recursion
    // stack
    bool *visited = new bool[V];
    for (int i = 0; i < V; i++)
        visited[i] = false;

    // Call the recursive helper
    // function to detect cycle in different
    // DFS trees
    for (int u = 0; u < V; u++)
    {
    
        // Don't recur for u if
        // it is already visited
        if (!visited[u])
        if (isCyclicUtil(u, visited, -1))
            return true;
    }
    return false;
}

// Driver program to test above functions
int main()
{
    Graph g1(5);
    g1.addEdge(1, 0);
    g1.addEdge(0, 2);
    g1.addEdge(2, 1);
    g1.addEdge(0, 3);
    g1.addEdge(3, 4);
    g1.isCyclic()?
    cout << "Graph contains cycle\n":
    cout << "Graph doesn't contain cycle\n";

    Graph g2(3);
    g2.addEdge(0, 1);
    g2.addEdge(1, 2);
    g2.isCyclic()?
    cout << "Graph contains cycle\n":
    cout << "Graph doesn't contain cycle\n";
  
    Graph g3(4);
    g3.addEdge(1, 2);
    g3.addEdge(2, 3);
    g3.isCyclic()?
    cout << "Graph contains cycle\n":
    cout << "Graph doesn't contain cycle\n";

    return 0;
}

此代码中有两个标记块,即块 1 和块 2。

当我使用第二个块时,这段代码输出正确。 但是如果我使用第一个块而不是第二个块,它会打印出不同的东西。

我的问题是第一块和第二块代码使用不同的逻辑吗? 如果不是那么为什么块 1 打印与第二块不同?

考虑否定条件,因为这会影响 else 分支的执行时间。

在commented-out代码中,是

!(!visited[i] && isCyclicUtil(i, visited, v))

也就是

visited[i] || !isCyclicUtil(i, visited, v)

你的整个条件,首先测试否定条件,等同于

if (visited[i] || !isCyclic(i, visited, v)) {
    if (i != parent)
        return true;
}
else {
    return true;
}

在“实时”代码中,否定是

!(!visited[i])

也就是

visited[i]

并且整个条件等同于

if (visited[i]) {
    if (i != parent) {
        return true;
    }
}
else if (isCyclicUtil(i, visited, v)) {
    return true;
}