Un graphe (S,F) est donné par
Un chemin dans G est une suite
Variantes:
Les graphes se rencontrent comme:
On se donne un graphe G=(S,F) par sa matrice d'adjacence A.
On veut calculer
la fermeture transitive de G, i.e. le graphe
G*=(S,F*) défini
par
ssi
Propriété fondamentale de la matrice d'adjacence:
Formule donnant la matrice d'adjacence A* de G*( en booléens):
Algorithme naïf en O(n4).
class Matrice {
int[][] m; //matrice carree
int n; //la dimension de m
Matrice(int x) {
n=x;
m=new int[n][n];
}
}
Calcul sur place dans une matrice T:
static void Warshall(Matrice T) {
int k,i,j;
for (k= 0; k< T.n; ++k)
for (i= 0; i< T.n; ++i)
if (T.m[i][k]== 1)
for (j= 0; j< T.n; ++j)
if(T.m[k][j]== 1)
T.m[i][j]= 1;
}
La complexité devient O(n3). C'est un exemple où on
peut améliorer la complexité sans rien perdre.
On représente le graphe par une matrice C définie par
On pose ensuite C(k)ij = la longueur du plus court chemin de i à jutilisant au plus k flèches.Du fait que les longueurs sont positives, on a la relation de récurrence:
Ceci conduit à un algorithme en O(n4).
On écrit l'algorithme comme une fonction qui transforme le tableau A sur place et renvoie un tableau P servant à retrouver un plus court chemin.
static Matrice Floyd(Matrice A) {
Matrice P=new Matrice(A.n);
for (int i=0; i< P.n; i++)
for (int j=0; j<P.n; j++)
P.m[i][j]= -1;
for (int k= 0; k< A.n; ++k)
for (int i= 0; i< A.n; ++i)
for (int j= 0; j< A.n; ++j)
if (A.m[i][k]+A.m[k][j] < A.m[i][j]) {
A.m[i][j]= A.m[i][k]+A.m[k][j];
P.m[i][j]= k;
}
return P;
}
Pour retrouver un plus court chemin, on ecrit la fonction suivante qui affiche les sommets utilisés.
static void chemin (int i, int j, Matrice P) {
int k;
k= P.m[i][j];
if (k != -1) {
chemin(i,k,P);
System.out.println(k);
chemin(k,j,P);
}
}
Il suffit de vérifier que P[i,j]=-1 ssi le plus
court chemin de i à j est une flèche et
que si P[i,j]=k, le plus court chemin de ià j passe par k.