A graph with vertices is a tree if and only if:
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.
|V| = |E| + 1. If the graph is a tree, then it contains n - 1 edges
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:
There is an edge , that is g[v][i] = 1;
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, cIf the graph is no longer a tree (flag = 1), there is no need to continue the search.
if flag: returnMark the vertex as visited.
used[v] = 1The vertex is visited, increase by .
c += 1The 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 = 0All vertices are initially unvisited (initialize the list with zeroes).
used = [0] * nCreate 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 cMark the vertex as visited.
used[v] = 1The vertex is visited, increase by .
c += 1Iterate over the vertices , that can be reached from . Moving from to is possible if:
There is an edge , that is g[v][i] = 1;
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 = 0All 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 //= 2Count the number of visited vertices during the depth-first search in variable .
c = 0Start 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")