Problemdə bağlantılı yönsüz qraf verilmişdir. İstənilir ki, bunun bir dövrə (Formula-0 yoluna çevrilə biləcək) ehtiva edib-etmədiyini yoxlamaqdır.
Yönsüz bir qrafda dövrə mövcuddur, əgər geri dönən bir kənar varsa. Yəni, artıq keçilmiş bir zirvəyə gedən kənar varsa.
Misal
Misaldakı qrafların şəkli belədir:
Birinci qraf dövrə ehtiva edir, ikincisi isə etməz.
Alqoritmin təsviri
Qrafı qonşuluq matrisi ilə saxlayırıq. visited adlı array-i isə keçilmiş zirvələri işarələmək üçün istifadə edirik.
#define MAX 1010
int g[MAX][MAX], used[MAX];dfs funksiyası zirvə -dən dərinlik üzrə axtarışı həyata keçirir. Və uca bir zirvədən -ə yönəldiyimiz vəziyyətdə (atmış, dövrə olmadığı halda) halı kəsib atmamız lazımdır. Bunun üçün dfs funksiyasında ikinci parametr — zirvə -nin atası parametrini daxil edəcəyik.
void dfs(int v, int p = -1)
{Zirvə işarələnmiş kimi qəbul edilir.
used[v] = 1;zirvəsindən keçilə biləcək zirvələri ilə keçiririk.
for (int i = 1; i <= n; i++)
{Ataya yönələn kənar xaric belə situasiya yoxlanır.
if (i == p) continue;-dən -yə, -nin artıq keçilmiş olduğu bir kənarın var olduğu hallar üçün (yəni, used[i] = 1), qrafda bir dövrə mövcuddur. flag = 1 olaraq təyin edilir.
if (g[v][i] == 1)
{
if (used[i] == 1) flag = 1;Əks halda, zirvəsindən dərinlik üzrə axtarışı davam edirik.
else dfs(i, v);
}
}
}Proqramın əsas hissəciyi. Giriş məlumatlarını oxuyuruq.
scanf("%d %d",&n,&m);
memset(g,0,sizeof(g));
memset(used,0,sizeof(used));Girişdəki yönsüz qrafı oxuyuruq. Qrafı qonşuluq matrisi olaraq saxladığımızdan təkrarlanan yollar yalnız bir dəfə nəzərə alınacaqdır.
for (i = 0; i < m; i++)
{
scanf("%d %d",&u,&v);
g[u][v] = g[v][u] = 1;
}Əvvəlcə qrafda dövrənin mövcud olmadığını göstərən flag = 0 olaraq təyin edirik. Dövrə tapılsa, flag dəyişəni 1 olacaq.
flag = 0;Zirvə 1-dən (tapşırıqda qrafın bağlantı olduğunu nəzərə alaraq) dərinlik üzrə axtarışı başlatırıq.
dfs(1);Flag dəyişəninə görə cavabı çıxardırıq.
if (flag) printf("YES\n");
else printf("NO\n");Java tətbiqi
import java.util.*;
public class Main
{
static int g[][], used[];
static int n, m, flag;
static void dfs(int v, int prev)
{
used[v] = 1;
for(int i = 1; i <= n; i++)
if ((i != prev) && g[v][i] == 1)
if (used[i] == 1) flag = 1; else dfs(i,v);
}
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
n = con.nextInt();
m = con.nextInt();
g = new int[n+1][n+1];
used = new int[n+1];
for(int i = 0; i < m; i++)
{
int u = con.nextInt();
int v = con.nextInt();
g[u][v] = g[v][u] = 1;
}
flag == 0;
dfs(1,-1);
if (flag == 1) System.out.println("YES");
else System.out.println("NO");
}
} Python tətbiqi
dfs funksiyası zirvə -dən dərinlik üzrə axtarışı həyata keçirir. Və uca bir zirvədən -ə yönəldiyimiz vəziyyətdə (atmış, dövrə olmadığı halda) halı kəsib atmamız lazımdır. Bunun üçün dfs funksiyasında ikinci parametr — zirvə -nin atası parametrini daxil edəcəyik.
def dfs(v, p = -1):
global flagZirvə keçilmiş kimi işarələnir.
used[v] = 1zirvəsindən keçilə biləcək zirvələri ilə keçiririk.
for i in range(1, n + 1):Ataya yönələn kənar xaric belə situasiya yoxlanır.
if i == p:
continue-dən -yə, -nin artıq keçilmiş olduğu bir kənarın var olduğu hallar üçün (yəni, used[i] = 1), qrafda bir dövrə mövcuddur. flag = 1 olaraq təyin edilir.
if g[v][i] == 1:
if used[i] == 1:
flag = 1Əks halda, zirvəsindən dərinlik üzrə axtarışı davam edirik.
else:
dfs(i, v)Proqramın əsas hissəciyi. Giriş məlumatlarını oxuyuruq.
n, m = map(int, input().split())
g = [[0] * (n + 1) for _ in range(n + 1)]
used = [0] * (n + 1)Girişdəki yönsüz qrafı oxuyuruq. Qrafı qonşuluq matrisi olaraq saxladığımızdan təkrarlanan yollar yalnız bir dəfə nəzərə alınacaqdır.
for _ in range(m):
a, b = map(int, input().split())
g[a][b] = g[b][a] = 1Əvvəlcə qrafda dövrənin mövcud olmadığını göstərən flag = 0 olaraq təyin edirik. Dövrə tapılsa, flag dəyişəni 1 olacaq.
flag = 0Zirvə 1-dən (tapşırıqda qrafın bağlantı olduğunu nəzərə alaraq) dərinlik üzrə axtarışı başlatırıq.
dfs(1)Flag dəyişəninə görə cavabı çıxardırıq.
if flag == 1:
print("YES")
else:
print("NO")