Étant donné un graphe non dirigé et non valué, vous voulez connaître son diamètre:
la plus grande distance entre 2 noeuds.
Problème: votre graphe peut être très grand (des millions de noeuds!).
On ne peut donc pas calculer la valeur exacte en faisant, par exemple, un BFS depuis chaque noeud...
On va donc calculer une valeur approchée: une borne inférieure. Cf le cours -- pour ceux qui n'ont pas écouté, demandez-moi.
Vous allez notamment réutiliser l'implémentation de graphe du TD1 et le BFS du TD2, qui sont dans test.tar.gz.
-
Complétez dans le fichier diam1.cc la fonction DiametreLB() décrite dans le fichier diam1.h:
#ifndef __DIAM1_H
#define __DIAM1_H
#include <utility>
#include "ugraph.h"
using namespace std;
// Étant donné un graphe, cette fonction trouve 2 noeuds dont la distance
// (la longueur du plus court chemin entre ces 2 noeuds) est la plus grande
// possible: cela représentera une borne inférieure du diamètre.
//
// ATTENTION:
// Votre algorithme devra tourner en un temps maximal imparti par graphe:
// Tmax = 50ms + (M+N)*1µs, où M est le nombre d'arêtes et N de noeuds.
// Ça correspond a du O(M+N).
// Par exemple, si M = 10M (10 millions), N = 1M (1million), Tmax = 11.05s.
//
// Ensuite, le score dépendra uniquement du diamètre obtenu: plus il est
// grand, meilleur sera votre score.
// Mais si le temps dépasse (sur ma machine!), le score sera 0: gardez une
// bonne marge!
pair<int, int> DiametreLB(const UndirectedGraph& graph);
#endif // __DIAM1_H
Test:
rm test.tar.gz; wget --no-cache http://fabien.viger.free.fr/oc/td6/test.tar.gz
tar xf test.tar.gz
make diam1
RENDU: diam1.cc
-
Implémentez dans un fichier diam2.cc la fonction DiametreUB() décrite dans le fichier diam2.h:
#ifndef __DIAM2_H
#define __DIAM2_H
#include <vector>
#include "ugraph.h"
using namespace std;
// Étant donné un graphe, cette fonction renvoie soit:
// - un noeud (donc, un vector<int> avec un seul élément) "central",
// qui minimise le "rayon" du graphe pour ce centre: le "rayon" est
// la plus grande distance à un autre noeud du graphe.
// - une sous-clique centrale, c'est-à-dire un sous-ensemble de noeuds
// tels qu'ils soient tous directement connectés entre eux par une
// arête, et tel que le "rayon" soit minimal pour ce "multi-centre".
//
// Dans les 2 cas, on peut déduire une borne supérieure sur le diamètre
// du graphe:
// - si on a renvoyé un noeud de rayon R: Diamètre <= 2*R
// - si on a renvoyé une sous-clique de rayon R: Diamètre <= 2*R+1
//
// Pour faire simple, vous pourrez vous limiter à renvoyer un simple noeud.
// Pour être un peu meilleur, vous pourrez renvoyer une arête (2 noeuds
// liés par une arête). Voire une sous-clique...
//
// ATTENTION:
// Même temps maximal imparti que pour l'exercice précédent.
// Le score sera fonction de la borne sup du diamètre (voire formule en haut):
// plus elle est petite, meilleur sera le score.
vector<int> DiametreUB(const UndirectedGraph& graph);
#endif // __DIAM2_H
Test: make diam2
RENDU: diam2.cc
|
|
|