Per calcolare il diametro e il raggio, abbiamo bisogno delle distanze minime tra tutte le coppie di vertici. Indichiamo con v_1, v_2, \ldots, v_n i vertici del grafo, e con d(v_i, v_j) la distanza minima tra i vertici v_i e v_j. Costruiamo la matrice di tutte queste distanze utilizzando l'algoritmo di Floyd — Warshall.
Algoritmo di Floyd — Warshall. Inizialmente, d(v_i, v_j) è uguale al peso dell'arco tra i vertici v_i e v_j, oppure infinito se tale arco non esiste; d(v_i, v_i) = 0. Poi iteriamo sui vertici v_k uno per uno e, per ogni coppia di vertici (v_i, v_j), verifichiamo se il percorso diventa più corto passando per il vertice v_k:
Dopo aver elaborato il vertice v_k, la matrice contiene le lunghezze dei cammini minimi i cui vertici intermedi si trovano tutti tra v_1, \ldots, v_k. Pertanto, dopo aver elaborato tutti gli vertici, la matrice contiene le distanze minime richieste.
Eccentricità. L'eccentricità r(v_i) del vertice v_i è uguale all'elemento massimo della -esima riga della matrice delle distanze minime:
Il diametro del grafo è la distanza massima tra una coppia di vertici, ossia il massimo delle eccentricità r(v_i). Il raggio del grafo è il minimo delle eccentricità r(v_i).
Esempio
Il grafo dato nell'esempio è mostrato di seguito. La figura a sinistra evidenzia il cammino minimo la cui lunghezza è uguale al diametro, mentre la figura a destra evidenzia il vertice la cui eccentricità è uguale al raggio.
Calcoliamo le distanze minime tra tutte le coppie di vertici. Ad esempio, non c'è nessun arco tra i vertici e . Il percorso 2 \to 4 \to 3 ha lunghezza 5 + 4 = 9, mentre il percorso 2 \to 4 \to 1 \to 3 è più corto: 5 + 2 + 1 = 8, quindi d(v_2, v_3) = 8. Analogamente, d(v_3, v_4) = 3: il percorso 3 \to 1 \to 4 di lunghezza 1 + 2 = 3 è più corto dell'arco diretto di peso .
La matrice delle distanze minime e le eccentricità dei vertici sono le seguenti:
\boldsymbol{r(v_i)} | |||||
L'eccentricità massima è uguale a ed è raggiunta nei vertici e — questo è il diametro del grafo. L'eccentricità minima è uguale a ed è raggiunta nel vertice — questo è il raggio del grafo.
Implementazione dell'algoritmo
Dichiariamo le costanti e la matrice dei pesi del grafo . Un arco mancante è indicato con "infinito" INF = \mathrm{0x3F3F3F3F}. Questo valore è sicuramente maggiore della lunghezza di qualsiasi cammino minimo (che non supera 99 \cdot 1000). Allo stesso tempo, la somma di due infiniti rientra comunque nel tipo , quindi non si verifica overflow nel calcolo di g[i][k] + g[k][j].
#define MAX 110
#define INF 0x3F3F3F3F
int g[MAX][MAX];La funzione floyd implementa l'algoritmo di Floyd — Warshall. Il ciclo esterno itera sul vertice intermedio . Per ogni coppia di vertici , verifichiamo se il percorso da a può essere accorciato passando per il vertice . Se g[i][k] + g[k][j] < g[i][j], aggiorniamo il valore g[i][j]. Le distanze minime vengono calcolate direttamente nella matrice .
void floyd(void)
{
int i, j, k;
for(k = 0; k < n; k++)
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
if (g[i][k] + g[k][j] < g[i][j])
g[i][j] = g[i][k] + g[k][j];
}La parte principale del programma. Leggiamo il numero di vertici e la matrice di adiacenza del grafo. Il valore significa che non c'è nessun arco; lo sostituiamo con .
scanf("%d",&n);
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
{
scanf("%d",&g[i][j]);
if (g[i][j] < 0) g[i][j] = INF;
}Calcoliamo le distanze minime tra tutte le coppie di vertici. Dopo la chiamata a , il valore g[i][j] è uguale alla distanza minima tra i vertici e .
floyd();Per ogni vertice , calcoliamo la sua eccentricità — l'elemento massimo della -esima riga della matrice . Il massimo di tutte le eccentricità è uguale al diametro del grafo , e il minimo è uguale al raggio del grafo .
diam = 0; radius = INF;
for(i = 0; i < n; i++)
{
max = 0;
for(j = 0; j < n; j++)
if (g[i][j] > max) max = g[i][j];
if (max > diam) diam = max;
if (max < radius) radius = max;
}Stampiamo il diametro e il raggio del grafo.
printf("%d\n%d\n",diam,radius);Implementazione in Java
import java.util.Scanner;
public class Main
{
static final int INF = 0x3F3F3F3F;
static int g[][];
static int n;
static void floyd()
{
for(int k = 0; k < n; k++)
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
if (g[i][k] + g[k][j] < g[i][j])
g[i][j] = g[i][k] + g[k][j];
}
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
n = con.nextInt();
g = new int[n][n];
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
{
g[i][j] = con.nextInt();
if (g[i][j] < 0) g[i][j] = INF;
}
floyd();
int diam = 0, radius = INF;
for(int i = 0; i < n; i++)
{
int max = 0;
for(int j = 0; j < n; j++)
if (g[i][j] > max) max = g[i][j];
if (max > diam) diam = max;
if (max < radius) radius = max;
}
System.out.println(diam + "\n" + radius);
con.close();
}
}