Розбір
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.
. If the graph is a tree, then it contains 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 realization — 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 , 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 and vertex is already visited . If a cycle is detected, set . 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 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 or if the graph is not connected .
if (flag || (c != n)) printf("NO\n"); else printf("YES\n");
Algorithm realization — 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 ;
The vertex is not visited
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 , and also if it is connected .
if ((Edges == n - 1) && (c == n)) printf("YES\n"); else printf("NO\n");
Java realization
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 realization – 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 , 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 and vertex is already visited . If a cycle is detected, set . 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 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 or if the graph is not connected .
if flag or c != n: print("NO") else: print("YES")
Python realization — 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:
There is an edge , that is ;
The vertex is not visited
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 , and also if it is connected .
if Edges == n - 1 and c == n: print("YES") else: print("NO")