Passer au forum
language C (encore ...
 
Notifications
Retirer tout

[Fermé] language C (encore :D) : graphes !

22 Messages
9 Utilisateurs
0 Réactions
2,512 Vues
Tchenou
Inscrit : 10.05.2008
Elite Grinder

Yop !

Alors histoire de paufiner mon dernier projet sur une implantation de graphe , je vous soumets mon code , l'idée c'est d'implémenter les opérations de base sur un graphe dont on a "juste" la matrice des noeud et des aretes , ou chaque élément de la matrice représente la distance entre chaque noeud [i,j], si c'est = 0 ca veut dire qu'il n'y a pas de chemin entre les noeuds.

Les fonctions que j'ai déjà implémentées sont :

- distance : nommer tous les somemts a une distance < que x d'un sommet y

- parcours récursif du sommet : afficher tous les sommets atteignables a partir d'un sommet de base x (vu que c'est récursif, ca affiche le dernier sommet appellée en premier si vous suivez)

- chemin : retourne un chemin entre deux sommets x et y (c'est là que je dois surtout paufiner tout ca) ....

-hasCycle : retourne si un graphe a oui ou non un cycle du style (A->B->C->A)

-convexe : question a la con et flemme d'expliquer la théorie...

J'aurais surtout besoin d'aide pour paufiner la question chemin que j'utilise dans quasi tout le reste (+ une autre fonction que je dois encore pondre) ...

Elle doit me retrouver le premier chemin qu'elle trouve, pas forcément le plus court, juste un chemin,e t renvoyer true ou false selon qu'il y en ait un ou pas...

Si vous avez des indices ensuite pour une seconde fonction chemin qui elle renverrait le plus court des chemins , avec quelle structure de données je devrais l'implémenter, tout ca... Je suis preneur.


21 réponses
Tchenou Auteur du sujet
Tchenou
Inscrit : 10.05.2008
Elite Grinder

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void distance(int matriceD[5][5],int s,int r){

s--;
int j;

if (s>4 || s<0){
printf("Il n'y a que 5 sommets dans le graphe et ils sont numérotés de 1 a 5 \n");
return;
}

for (j=0;j<5;j++){
if (matriceD[j] <= r && matriceD[j] != 0) printf("%d ",j+1);
}

}

void clear(bool visited[5]){
int i = 0;
for (i=0;i<5;i++){
visited = false;
}
}

bool parcours(int matrice[5][5],int s, bool visited[5]){

s--;
visited = true;
int j = 0;

if (s>4 || s<0){
printf("Il n'y a que 5 sommets dans le graphe et ils sont numérotés de 1 a 5 \n");
return false;
}

for (j=0;j<5;j++){

if (matrice[j] != 0 ){

if (!visited[j]){
visited[j] = true;
parcours(matrice,j+1,visited);
}

}
}

printf("%d ",s+1);
return false;

}

bool sourceInactive(int matriceD[5][5],int s){
int i = 0;
for (i=0;i<5;i++){
if (matriceD != 0) return false;
}
return true;
}
bool isUnreachable(int matrice[5][5],int s){
int i = 0;
for (i=0;i<5;i++){
if (matrice != 0) return false;
}
return true;
}

bool allVisited(int matrice[5][5], bool visited[5]){
int i = 0;
for (i=0;i<5;i++){
if (isUnreachable(matrice,i)) visited = true;
if (visited != true) return false;
}
return true;
}

bool chemin(int matrice[5][5],int s,int e,bool affichage,bool visited[5]){

// if (s == e){
//
// if (affichage){
// printf("%d",e);
// return true;
// }
//
// else return false;
// }
int temp = 0;
int i = 0;

s--;
e--;

if (s == e){

for (i=0;i<5;i++){
if (matrice != 0){

clear(visited);
temp = matrice;
matrice = 0;

if (chemin(matrice,i+1,s+1,0,visited)){

if (affichage) printf("%d ",s+1);

clear(visited);

if (affichage) chemin(matrice,i+1,s+1,1,visited);

return true;

}

else matrice = temp;

}
}

if (affichage) printf("Meme sommet de depart et d arrivee et aucun cyle partant du noeud : pas de chemin");
return false;
}

visited = true;

int k = 1;
int chemin[5] = {s+1,0,0,0,0};

if (s>4 || e>4 || e<0 || s<0){
if (affichage) printf("Il n'y a que 5 sommets dans le graphe et ils sont numérotés de 1 a 5 \n");
return false;
}

if (isUnreachable(matrice,e)){
if (affichage) printf("Pas de chemin : le noeud arrive est isole des autres noeuds du graphe\n");
return false;
}
if (sourceInactive(matrice,s)){
if (affichage) printf("Pas de chemin : la source n'est connectée à aucun noeud du graphe\n");
return false;
}

while (s != e){

if (matrice == 0 && i == 4){

s = chemin[k-2]-1;
i = chemin[k-1];
chemin[k-1] = 0;

k--;
visited[e] = true;
if (allVisited(matrice,visited)){
if (affichage) printf("Pas de chemin : tous les traces potentiels ont echoue ! \n");
return false;
}
else visited[e] = false;
}
if (matrice > 0 && visited == false){

chemin[k] = i+1;
k++;
s = i;
visited = true;
i = -1;

}
i++;
}
if (affichage){
k = 0;
while(k < 5 && chemin[k] != 0){
printf("%d ",chemin[k]);
k++;
}
}
return true;
}

bool hasCycle(int matriceND[5][5], bool visited[5]){

int nmbAretes = 0;
int i,j = 0;

for (i=0;i<5;i++){
for (j=0;j<5;j++){
if (matriceND[j] != 0)nmbAretes++;
}
}

nmbAretes = nmbAretes/2;

if (nmbAretes >= 5){
return true;
}

else {

for (i=0;i<5;i++){
if (chemin(matriceND,i+1,i+1,0,visited)){
return true;
}
}
}
return false;

}

void connexe(int matriceND[5][5], bool visited[5]){

bool chemins[5][5] = {{false}};
int max = 0;
bool posMax[5] = {0};
int temp = 0;
bool posTemp[5] = {0};
int i,j = 0;

for (i=0;i<5;i++){
for (j=0;j<5;j++){
if (i != j){

if (matriceND[j] != 0) chemins[j] = true;

else {

clear(visited);

if (chemin(matriceND,i+1,j+1,0,visited)){
chemins[j] = true;
}

}
}
}
}

for (i=0;i<5;i++){

for (j=0;j<5;j++){

if (chemins[j] !=0){
temp++;
posTemp[j] = true;
}

}

if (temp > max){

max = temp;

for (j=0;j<5;j++){
posMax[j] = posTemp[j];
}

}

temp = 0;

for (j=0;j<5;j++){
posTemp[j] = false;
}

}

printf("Le nombre de composantes connexe maximal est de %d \n",max);
printf("Et les sommets qui les composes en sont : ");

for (j=0;j<5;j++){
if (posMax[j]) printf("%d ",j+1);
}

}

int main() {

int matriceD [5][5] = {{0,0,0,0,0},
{0,0,0,5,0},
{0,4,0,9,0},
{0,0,0,0,0},
{0,0,0,0,0}};

int matriceND2 [5][5] = {{0,6,0,0,0},
{6,0,4,0,0},
{0,4,0,9,0},
{0,0,9,0,0},
{0,0,0,0,0}};

int matriceND [5][5] = {{0,6,0,1,0},
{6,0,4,0,0},
{0,4,0,9,0},
{1,0,9,0,0},
{0,0,0,0,0}};

int matriceND3 [5][5] = {{0,6,0,0,2},
{6,0,4,0,3},
{0,4,0,9,0},
{0,0,9,0,10},
{2,3,0,10,0}};

bool visited[5] = {false};

distance(matriceD,2,5);
printf("\n");

clear(visited);
parcours(matriceD,3,visited);
printf("\n");

clear(visited);
chemin(matriceND,2,2,1,visited);
printf("\n");

if (hasCycle(matriceND,visited)) printf("Le graphe contient au moins un cycle");
else printf("Le graphe ne contient pas de cycle");
printf("\n");

clear(visited);
connexe(matriceND2,visited);
printf("\n");

return 0;

}

NB : matriceD c'est pour matrice digérée, autrement dit on ne peut parcourir les aretes que dans un sens, c'est pour les questions distance, et parcours et plus petit chemin.

ND, bah forcément c'est le contraire, et c'est pour les autres questions.


Tchenou Auteur du sujet
Tchenou
Inscrit : 10.05.2008
Elite Grinder

Merci d'avance a ceux qui auront le courage de se lancer la dedans :P


J'ai lu mais je n'ai rien compris, bon courage :transpire:


chika78
Inscrit : 06.08.2009
PokerStrategist

Putain, rien pigé !

Quelques questions/remarques d'ordre général cependant :

Si tu voulais travailler sur des matrices 6x6 ou 8x8, tu serais bien emm...bêté , alors qu'un simple petit #define THEDIM 5 te rendrait bien service :D

Il y a énormément d'endroits dans ton code ou tu peux utilement remplacer des tableaux par des pointeurs, dans les paramètres comme dans le traitement (genre bool *tableau au lieu de bool tableau[5])

jette un oeil à des fonctions comme memset et memcpy, c'est souvent plus simple et rapide pour RAZ ou copie.

sinon, pour le fun, la fonction clear peut s'écrire comme ça :

void clear(bool visited[5]) {
  for (int i=0; i<5; visited[i++]=false) ;
}

ou encore :

void clear(bool visited[5]) {
  memset(*visited, 0, sizeof(visited));
}

dans tes fonctions sourceInactive et isUnreacheable, plutôt que de passer un tableau à 2 dimensions et l'indice de la première dimension, pourquoi ne pas passer que le tableau de la 2ème dimension ?
genre : isUnreachable(matrice) au lieu de isUnreachable(matrice, i)

Sinon j'ai rien compris à l'objectif principal graphe / noeud / sommet / arête / toussa, mais on en est pas encore là. :D


Tchenou Auteur du sujet
Tchenou
Inscrit : 10.05.2008
Elite Grinder

Yop pour la dimension je compte pas la changer, le prof s'en cale d'ailleurs c'est plus l'implémentation générale, la dimension c'est juste pour pouvoir faire des essais avec des matrices et voir si ca marche.

Pour les passages de paramètres j'avais cru lire un article ou ils spécifiaient bien que c'était comme ca qu'ils fallaient envoyer un tableau multidimensionnel en paramètre, je veux bien essayer ta manière mais concrètement qu'est-ce que ca change ?

Pour les deux dernières améliorations, vu qu'on a pas vu ca au cours ca risque de faire suspect même si c'est plus bô :D

Sinon pour le sujet en général :

L’objectif de ce projet est d’implémenter des algorithmes simples sur des graphes. Dans ce projet, nous travaillerons sur des graphes dirigés et non-dirigés ayant n sommets.
Ces graphes seront pondérés (poids sur les arêtes) ; les poids représenteront la "distance"
entre les sommets. L’implémentation de ces graphes se fera grâce à une matrice d’adjacence
de taille n n. Les sommets sont simplement dénotés par des nombres de 1 à n.
Vous avez le droit de créer toutes les structures de données temporaires que vous jugerez
nécessaires, l’objectif étant d’obtenir un algorithme dont le pire cas du temps d’exécution (en
notation grand-O() ) soit le meilleur possible. Bien entendu, vous écrirez à chaque fois la
complexité en fonction de n, le nombre de sommets du graphe.

J'ai donc choisi pour le fun n = 5.

Chaque élément de la matrice (j'en ai créee plusieurs pour les essais) représente donc la distance entre deux noeuds du graphe.

Sinon si ca va tjs pas :

http://fr.wikipedia.org/wiki/Th%C3%A9orie_des_graphes

Ca va mieux pour le fonctionnement général ? :D


zarelle
Inscrit : 12.11.2008
Oldschool Grinder

Omg, rien compris non plus :D

Bon courage dans ton avancée


Babaisback33
Inscrit : 21.03.2009
Elite Grinder

Ca rappelle des cours manqués tout ça x)

Hf


chika78
Inscrit : 06.08.2009
PokerStrategist

Purée, extrait du début de wiki :

"La théorie des graphes est une théorie informatique et mathématique. Les algorithmes élaborés pour résoudre des problèmes concernant les objets de cette théorie ont de nombreuses applications dans tous les domaines liés à la notion de réseau (réseau social, réseau informatique, Télécom…) et dans bien d'autres domaines (e.g. génétique) tant le concept de graphe, à peu près équivalent à celui de relation binaire (à ne pas confondre donc avec graphe d'une fonction), est général. De grands théorèmes difficiles, comme le théorème des quatre couleurs et le théorème des graphes parfaits, ont contribué à asseoir cette matière auprès des mathématiciens, et les questions qu'elle laisse ouvertes, comme la conjecture d'Hadwiger, en font une branche vivace des mathématiques discrètes."

Tu m'étonnes qu'elles soient discrètes, ces maths-là. Manquerait plus qu'elles se fassent remarquer !

Les mouches serrent les fesses, lol.

Sinon, tu as écrit un algorithme d'abord ?


gwilhermc
Inscrit : 02.10.2009
Elite Grinder

la flemme de lire ton code (et en plus j'ai pas fait de C depuis 15 ans donc...)

parlons algorithmie.

quelle l'idée derrière ton code dans le programme "chemin"?


ZeNakedMan
Inscrit : 20.02.2011
PokerStrategist

Bon, jsais pas si le thread est dead mais jpeux tenter de donner un coup de main =)

Pour l'algo de recherche du chemin le plus court, il y a Djikstra.

En gros c'est du recursif, il change de chemin a chaque fois qu'il stock un chemin qui lui apparait plus long qu'un chemin déjà vu, et passe a se chemin, avant de rechanger dés que ce chemin est plus long qu'un autre déja vu.

C'est assez bien expliqué ici : http://fr.wikipedia.org/wiki/Algorithme_de_Dijkstra et plutôt facile a comprendre. Et intuitivement, tu devrais trouver un truc du genre.


Tchenou Auteur du sujet
Tchenou
Inscrit : 10.05.2008
Elite Grinder

Ok pour le plus court chemin !
Thread pas dead du tout, désolé je l'ai zappé pendant un jour ou deux

Sinon pour chemin vu qu'ell est importante :

Ma logique pour ma fonction chemin c'est de trouver un chemin reliant deux sommets le plus "rapidement" possible quelque soit sa taille.. En gros ca doit renvoyer true si y en a un, false si y en a pas, et ce le plus rapdiement possible (et parfois l'afficher quand j'en ai besoin, d'ou le dernier booleen en paramètre).

Si le noeud d'entrée = le noeud de sortie (première boucle) , j'essaye de partir de tous les noeuds accessibles directement depuis l'entrée et de revenir vers la sortie (récursivité) , si c'est possible pour un des sommets accessible, c'est qu'il y a un cycle dans le circuit donc

Je l'ai résolu comme cas a part car la suite de ma fonction buggait quand je mettais noeud entrée et noeud de sorties équivalents

Ensuite mon algo exclut les cas ou le noeud source et/ou le noeud arrivée ne sont connectés a aucun noeud pour aller plus vite

Pour la boucle principale (while s != e) en gros je parcours la matrice du graphe a partir de la ligne correspondant aux noeud sources, dès que je trouve un voisin accessible, je passe sur sa ligne et je signale qu'on l'a déjà visité (pour éviter les cycles et les boucles infinies) et je le rajoute dans le chemin potentiel reliant la source a l'arrivée.

Ensuite je recommence au début de la ligne du nouveau noeud, et je fais pareil. Si j'arrive au bout d'une ligne sans rien, je "reviens en arrièr" en supprimant le dernier noeud du chemin, et en recommancant au noeud précédent (en ignorant évidemment le noeud supprimé quand on repasse dans la ligne du noeud précédent, histoire de ne pas recommencer le même scénario)

Puis dès que s = e, j'ai trouvé un chemin et je le renvois

Des idées d'amélioration pour pourvoir déterminer plus vite quand il y a ou non un chemin entre deux noeud quelconques, sans se soucier de sa taille , juste le trouver le plus rapidement possible ?


jivjav
Inscrit : 20.02.2007
Elite Grinder

Ta fonction distance est incomplète :

Tu ne testes que les sommets directement reliés à e alors que tu peux très bien avoir une liaison du type e->y1->s avec une distance inférieure à ton paramètre x. Il faut simplement que tu changes ça en récurrence.

Pour l'algo, comme dit plus haut, il faut faire un dijkstra vu que tu n'as pas d'heuristique disponible pour mettre en place un A*. (dijkstra = A* avec heuristique nulle)

ça donnerait un truc comme ça :

bool chemin(int matrice[5][5],int s,int e,bool affichage){

s--;
e--;

int i;
int from[5] = {-1, -1, -1, -1, -1};
bool open[5] = {false, false, false, false, false};
bool closed[5] = {false, false, false, false, false};
int cost[5] = {0, 0, 0, 0, 0};
bool better;
int testCost;

/* on part du noeud e */
open[e] = true;

while(!allFalse(open, 5)) {
int current = indexOfLower(cost, open, 5);

if (current == s) {
/* On est arrivé, reconstruction du chemin */

if (affichage) {
printf("Chemin : ");
while(current != -1) {
printf("%d ", current+1);
current = from[current];
}
printf("\n");
}

return true;
}

open[current] = false;
closed[current] = true;

for (i = 0; i < 5; i++) {
if (matrice[current] != 0 && !closed) {
/* un voisin en dehors du closed set */
testCost = cost[current] + matrice[current];

if (!open) {
open = true;
better = true;
}
else {
better = (testCost < cost);
}

if (better) {
from = current;
cost = testCost;
}
}
}

}

if (affichage) {
printf("Pas de chemin !!");
}

return false;

}

avec allFalse et indexOfLower :

bool allFalse(bool* tab, int n) {
int i;
for (i = 0; i < n; i++) {
if (tab) return false;
}
return true;
}

int indexOfLower(int*tab, bool* open, int n) {
int i;
int minI = -1;
for (i = 0; i < n; i++) {
if (open && (minI == -1 || tab < tab[minI])) minI = i;
}
return minI;
}


Maxippouce
Inscrit : 21.08.2007
Oldschool Grinder

oops, je me suis perdu là, ....

je sors


Tchenou Auteur du sujet
Tchenou
Inscrit : 10.05.2008
Elite Grinder

Ok pour le plus court chemin et distra , mais en terme de complexité ce n'est pas la fonction la plus optimale non ?

En fait je dois utiliser ma fonction plus court chemin juste quand je dois effectivement trouver le plus court chemin (ce qui est en fait seulement un bonus dans mon énoncé ) donc le plus important c'est surtout que la complexité de ma fonction chemin actuelle soit la plus basse possible, donc je dois trouver l'algo le plus simple a implémenter et le plus court d exécution qui te dit si oui ou non il existe un chemin entre A et B et c'est tout, est-ce que ma fonction chemin actuelle répond a ces attentes ou doit-elle être optimisée ?

Ok pour la distance je modifie ca!


Tchenou Auteur du sujet
Tchenou
Inscrit : 10.05.2008
Elite Grinder

Ok pour le plus court chemin et distra , mais en terme de complexité ce n'est pas la fonction la plus optimale non ?

En fait je dois utiliser ma fonction plus court chemin juste quand je dois effectivement trouver le plus court chemin (ce qui est en fait seulement un bonus dans mon énoncé ) donc le plus important c'est surtout que la complexité de ma fonction chemin actuelle soit la plus basse possible, donc je dois trouver l'algo le plus simple a implémenter et le plus court d exécution qui te dit si oui ou non il existe un chemin entre A et B et c'est tout, est-ce que ma fonction chemin actuelle répond a ces attentes ou doit-elle être optimisée ?

Ok pour la distance je modifie ca!


chika78
Inscrit : 06.08.2009
PokerStrategist

Encore du récursif, obv :

#include <stdio.h>
#include <stdlib.h>

#define NBR_SOMMETS 5

typedef int typeMatrice[NBR_SOMMETS][NBR_SOMMETS];	// type de matrice
typedef int typeTabVisite[NBR_SOMMETS];	// tableau des visites


void razVisites(typeTabVisite visites) {
	int i;
	for (i = 0; i < NBR_SOMMETS; i++)
		visites[i] = 0;
}

/**
 * Retourne la distance entre 2 sommets, ou 0 si pas de liaison
 */
int distanceChemin(int sommet1, int sommet2, typeMatrice matrice, typeTabVisite visites) {
	if (matrice[sommet1][sommet2] > 0) {
		// on a trouve le lien direct, renvoie la distance
		return matrice[sommet1][sommet2];
	}
	int numSommet, dist=0;
	for (numSommet = 0; numSommet < NBR_SOMMETS; numSommet++) {
		// on cherche un chemin parmi les liaisons de sommet1
		if ( matrice[sommet1][numSommet] > 0 && !visites[numSommet] ) {
			visites[numSommet]=1;
			dist = distanceChemin(numSommet, sommet2, matrice, visites);
			visites[numSommet]=0;
			if (dist>0)
				return (dist + matrice[sommet1][numSommet]);
		}
	}
	return 0;
}

int main() {

	typeMatrice ND0 = {
		{ 0, 1, 0, 1, 0 },
		{ 1, 0, 1, 1, 0 },
		{ 0, 1, 0, 1, 1 },
		{ 1, 1, 1, 0, 0 },
		{ 0, 0, 1, 0, 0 },
	};
	typeMatrice ND1 = {
		{ 0, 0, 0, 1, 0 },
		{ 0, 0, 1, 0, 1 },
		{ 0, 1, 0, 1, 0 },
		{ 1, 0, 1, 0, 0 },
		{ 0, 1, 0, 0, 0 },
	};

	typeMatrice ND =  {
		{ 0, 6, 0, 0, 0},
		{ 6, 0, 4, 0, 0},
		{ 0, 4, 0, 9, 0},
		{ 0, 0, 9, 0, 0},
		{ 0, 0, 0, 0, 0}
	};

	int i, j;
	typeTabVisite v;

	// teste toutes les distances
	for (i = 0; i < NBR_SOMMETS; i++) {
		for (j = 0; j < NBR_SOMMETS; j++) {
			razVisites(v);
			if (i != j)
				printf("Existe %d vers %d: %d \n", i + 1, j + 1, distanceChemin(i, j, ND, v));
		}
	}
}

jivjav
Inscrit : 20.02.2007
Elite Grinder

Sans les couts, tu peux faire ça :

int firstTrue(bool* open, int n) {
    int i;
    for (i = 0; i < n; i++) {
        if (open[i]) return i;
    }
    return -1;
}


bool hasChemin(int matrice[5][5],int s,int e,bool affichage){

s--;
e--;

int i;
int from[5] = {-1, -1, -1, -1, -1};
bool open[5] = {false, false, false, false, false};
bool closed[5] = {false, false, false, false, false};

/* on part du noeud e */
open[e] = true;

while(!allFalse(open, 5)) {
    int current = firstTrue(open, 5);

    if (matrice[current][s] != 0 || current == s) {
        /* On a un accès direct à la case finale */

        if (affichage) {
            if (current != s) from[s] = current;
            current = s;

            printf("Chemin : ");
            while(current != -1) {
                printf("%d ", current+1);
                current = from[current];
            }
                printf("\n");
        }

        return true;
    }

    open[current] = false;
    closed[current] = true;

    for (i = 0; i < 5; i++) {
        if (matrice[current][i] != 0 && !closed[i] && !open[i]) {
            /* un voisin en dehors de la closed list et de l'open list */

            open[i] = true;
            from[i] = current;
        }
    }

}

if (affichage) {
    printf("Pas de chemin !!\n");
}

return false;

}

Tchenou Auteur du sujet
Tchenou
Inscrit : 10.05.2008
Elite Grinder

Yop !

Donc ce code est plus optimal que ma version actuelle de chemin alors I guess ?

Ok pour la distance, vais également m'occuper du plus petit chemin existant

Sinon j'aurai encore une dernière question quand j'aurai déjà paufiné tout ca, puisqu'on me demande de réaliser un "arbre couvrant" et que j'avoue que je cale un peu !

Merci à tous


chika78
Inscrit : 06.08.2009
PokerStrategist

Autre version, capable de trouver le chemin le + court :

#include <stdio.h>
#include <stdlib.h>

#define NBR_SOMMETS 5
#define MAXIMUM 99999999

typedef int typeMatrice[NBR_SOMMETS][NBR_SOMMETS];	// type de matrice
typedef int typeTabVisite[NBR_SOMMETS];	// tableau des visites


void razVisites(typeTabVisite visites) {
	int i;
	for (i = 0; i < NBR_SOMMETS; i++)
		visites[i] = 0;
}

/**
 * Retourne la distance entre 2 sommets, ou 0 si pas de liaison
 * Si findMini <> 0, renvoie la distance du chemin le plus court
 * Si findMini = 0, renvoie la distance du premier chemin trouvé
 */
int distanceChemin(int sommet1, int sommet2, typeMatrice matrice, typeTabVisite visites, int findMini) {
	if (matrice[sommet1][sommet2] > 0) {
		// on a trouve le lien direct, renvoie la distance
		return matrice[sommet1][sommet2];
	}
	int distMini=MAXIMUM;
	int numSommet, dist=0;
	for (numSommet = 0; numSommet < NBR_SOMMETS; numSommet++) {
		// on cherche un chemin parmi les liaisons de sommet1
		if ( matrice[sommet1][numSommet] > 0 && !visites[numSommet] ) {
			visites[numSommet]=1;
			dist = distanceChemin(numSommet, sommet2, matrice, visites, findMini);
			visites[numSommet]=0;
			if (dist>0) {
				dist += matrice[sommet1][numSommet];
				// mode recherche chemin mini ?
				if (findMini) {
					// on conserve la distance la + courte
					if (dist < distMini) distMini = dist;
					// et on continue la recherche
				}
				else {
					return dist;
				}
			}
		}
	}
	return (findMini ? (distMini < MAXIMUM ? distMini : 0) : 0);
}

int main() {

	typeMatrice ND =  {
		{ 0, 6, 0, 5, 0},
		{ 6, 0, 4, 0, 0},
		{ 0, 4, 0, 9, 0},
		{ 5, 0, 9, 0, 0},
		{ 0, 0, 0, 0, 0}
	};

	int i, j;
	typeTabVisite v;

	// teste toutes les distances
	for (i = 0; i < NBR_SOMMETS; i++) {
		for (j = 0; j < NBR_SOMMETS; j++) {
			razVisites(v);
			if (i != j)
				printf("Le + court entre %d et %d: %d \n", i + 1, j + 1, distanceChemin(i, j, ND, v, 1));
		}
	}
}