Is it a Tree?#977

Is it a Tree? (Editorial)

A graph with vertices is a tree if and only if:

  1. The graph is connected. Start a depth-first search from the first vertex. Count the number of visited vertices during the search. If it equals , then the graph is connected.

  2. |V| = |E| + 1. If the graph is a tree, then it contains n - 1 edges

  3. The graph does not contain cycles. Start a depth-first search from the first vertex. If a back edge exists, then the graph has a cycle and is not a tree.

Satisfying conditions and or and is sufficient for the graph to be a tree.

Example

The graph provided in the example is a tree.

Algorithm implementation — checking the conditions 1) and 3)

Declare the adjacency matrix of the graph and the array .

#define MAX 110
int g[MAX][MAX], used[MAX];

The dfs function performs a depth-first search starting from vertex . The parent of vertex is . If a cycle is detected, the variable is set to .

void dfs(int v, int p)
{

If the graph is no longer a tree (flag = 1), there is no need to continue the search.

  if (flag) return;

Mark the vertex as visited.

  used[v] = 1;

The vertex is visited, increase by .

  c++;

The edge will be a back edge and form a cycle if i \ne p and vertex is already visited (used[i] = 1). If a cycle is detected, set flag = 1. If no cycle is detected, continue the search from vertex .

  for(int i = 0; i < n; i++)
    if ((i != p) && g[v][i])
      if(used[i]) flag = 1; else dfs(i,v);
}

The main part of the program. Read the input data.

scanf("%d",&n); 
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
  scanf("%d",&g[i][j]);

Count the number of visited vertices during the depth-first search in the variable . Set flag = 0 if there is no cycle in the graph. If a cycle is detected, becomes .

c = 0;
flag = 0;

All vertices are initially unvisited (initialize the array with zeroes).

memset(used,0,sizeof(used));

Start the depth-first search from vertex . Since it is the root of the tree, it has no parent. Pass the value as the second argument to the dfs function.

dfs(0,-1);

The graph is not a tree if there is a back edge (flag = 1) or if the graph is not connected (c \ne n).

if (flag || (c != n)) printf("NO\n"); else printf("YES\n");

Algorithm implementation — checking the conditions 1) and 2)

Declare the adjacency matrix of the graph and the array .

#define MAX 101
int g[MAX][MAX], used[MAX];

The dfs function implements depth-first search from vertex .

void dfs(int v)
{

Mark the vertex as visited.

  used[v] = 1;

Vertex is visited, increase by .

  c++;

Iterate over the vertices , that can be reached from . Moving from to is possible if:

  1. There is an edge , that is g[v][i] = 1;

  2. The vertex is not visited (used[i] = 0)

If both conditions are true, we continue the depth-first search from vertex .

  for (int i = 1; i <= n; i++)
    if (g[v][i] && !used[i]) dfs(i);
}

The main part of the program. Read the input value of .

scanf("%d", &n); 

Count the number of edges in the graph in the variable .

Edges = 0;

All vertices are initially unvisited (initialize the array with zeroes).

memset(used, 0, sizeof(used));

Read the adjacency matrix . Count the number of edges in the graph.

for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
{
  scanf("%d", &g[i][j]);
  Edges += g[i][j];
}

Since the graph is undirected, edges and are considered the same. Divide the value of by .

Edges /= 2;

Count the number of visited vertices during the depth-first search in variable .

c = 0;

Start the depth-first search from the vertex .

dfs(1);

The graph is a tree if the number of edges in it equals n - 1, and also if it is connected (c = n).

if ((Edges == n - 1) && (c == n)) printf("YES\n");
else printf("NO\n");

Java implementation

import java.util.*;
//import java.io.*;

public class Main
{
  static int c = 0; 	
  static int m[][], used[];
  
  static void dfs(int v)
  {
    used[v] = 1; c++;
    for(int i = 0; i < m.length; i++) 
      if (m[v][i]== 1 && used[i] == 0) dfs(i);
  }
  
  public static void main(String[] args) //throws IOException
  {
    Scanner con = new Scanner(System.in);
    //Scanner con = new Scanner(new FileReader ("977.in"));
    int n = con.nextInt();
    m = new int[n][n];
    used = new int[n];
    Arrays.fill(used, 0);
    int Edges = 0;
    
    for(int i = 0; i < n; i++)
    for(int j = 0; j < n; j++)
    {
      m[i][j] = con.nextInt();
      Edges += m[i][j];
    }

    dfs(0); Edges /= 2;

    if ((Edges == n - 1) && (c == n)) 
      System.out.printf("YES"); 
    else 
      System.out.printf("NO");    
  }
}   

Python implementation — checking the conditions 1) and 3)

The dfs function performs a depth-first search starting from vertex . The parent of vertex is . If a cycle is detected, the variable is set to .

def dfs(v, p):

Declare the global variables used by the function.

  global flag, c

If the graph is no longer a tree (flag = 1), there is no need to continue the search.

  if flag: return

Mark the vertex as visited.

  used[v] = 1

The vertex is visited, increase by .

  c += 1

The edge will be a back edge and form a cycle if i \ne p and vertex is already visited (used[i] = 1). If a cycle is detected, set flag = 1. If no cycle is detected, continue the search from vertex .

  for i in range(n):
    if i != p and g[v][i]:
      if used[i]: flag = 1
      else: dfs(i, v)

The main part of the program. Read the input value of .

n = int(input())

Count the number of visited vertices during the depth-first search in the variable . Set flag = 0 if there is no cycle in the graph. When a cycle is detected, becomes .

c = 0
flag = 0

All vertices are initially unvisited (initialize the list with zeroes).

used = [0] * n

Create an adjacency matrix , initially filled with zeroes.

g = [[0] * n for _ in range(n)]

Read the input adjacency matrix.

for i in range(n):
  g[i] = list(map(int, input().split()))

Start the depth-first search from vertex . Since it is the root of the tree, it has no parent. Pass the value as the second argument to the dfs function.

dfs(0, -1)

The graph is not a tree if there is a back edge (flag = 1) or if the graph is not connected (c \ne n).

if flag or c != n:
  print("NO")
else:
  print("YES")

Python implementation — checking the conditions 1) and 2)

The dfs function implements depth-first search from vertex .

def dfs(v):
  global c

Mark the vertex as visited.

  used[v] = 1

The vertex is visited, increase by .

  c += 1

Iterate over the vertices , that can be reached from . Moving from to is possible if:

  1. There is an edge , that is g[v][i] = 1;

  2. The vertex is not visited (used[i] = 0)

If both conditions are true, we continue the depth-first search from vertex .

  for i in range(1, n + 1):
    if g[v][i] and not used[i]: dfs(i)

The main part of the program. Read the input value of .

n = int(input())

Count the number of edges in the graph in the variable .

Edges = 0

All vertices are initially unvisited (initialize the array with zeroes).

used = [0] * (n + 1)

Create an adjacency matrix , initially filled with zeroes.

g = [[0] * (n + 1) for _ in range(n + 1)]

Read the adjacency matrix . Count the number of edges in the graph.

for i in range(1, n + 1):
  g[i] = [0] + list(map(int, input().split()))
  Edges += sum(g[i])

Since the graph is undirected, edges and are considered the same. Divide the value of by .

Edges //= 2

Count the number of visited vertices during the depth-first search in variable .

c = 0

Start the depth-first search from the vertex .

dfs(1)

The graph is a tree if the number of edges in it equals n - 1, and also if it is connected (c = n).

if Edges == n - 1 and c == n:
  print("YES")
else:
  print("NO")