Para calcular el diámetro y el radio, necesitamos las distancias más cortas entre todos los pares de vértices. Denotemos por v_1, v_2, \ldots, v_n los vértices del grafo, y por d(v_i, v_j) la distancia más corta entre los vértices v_i y v_j. Construimos la matriz de todas estas distancias usando el algoritmo de Floyd — Warshall.
Algoritmo de Floyd — Warshall. Inicialmente, d(v_i, v_j) es igual al peso de la arista entre los vértices v_i y v_j, o infinito si no existe tal arista; d(v_i, v_i) = 0. Luego iteramos sobre los vértices v_k uno por uno y, para cada par de vértices (v_i, v_j), verificamos si el camino se acorta al pasar por el vértice v_k:
Después de procesar el vértice v_k, la matriz contiene las longitudes de los caminos más cortos cuyos vértices intermedios se encuentran todos entre v_1, \ldots, v_k. Por lo tanto, después de procesar los vértices, la matriz contiene las distancias más cortas requeridas.
Excentricidades. La excentricidad r(v_i) del vértice v_i es igual al elemento máximo de la -ésima fila de la matriz de distancias más cortas:
El diámetro del grafo es la distancia máxima entre un par de vértices, es decir, el máximo de las excentricidades r(v_i). El radio del grafo es el mínimo de las excentricidades r(v_i).
Ejemplo
El grafo dado en el ejemplo se muestra a continuación. La figura de la izquierda resalta el camino más corto cuya longitud es igual al diámetro, y la figura de la derecha resalta el vértice cuya excentricidad es igual al radio.
Calculemos las distancias más cortas entre todos los pares de vértices. Por ejemplo, no hay arista entre los vértices y . El camino 2 \to 4 \to 3 tiene longitud 5 + 4 = 9, mientras que el camino 2 \to 4 \to 1 \to 3 es más corto: 5 + 2 + 1 = 8, por lo que d(v_2, v_3) = 8. De manera similar, d(v_3, v_4) = 3: el camino 3 \to 1 \to 4 de longitud 1 + 2 = 3 es más corto que la arista directa de peso .
La matriz de distancias más cortas y las excentricidades de los vértices son las siguientes:
\boldsymbol{r(v_i)} | |||||
La excentricidad máxima es igual a y se alcanza en los vértices y — este es el diámetro del grafo. La excentricidad mínima es igual a y se alcanza en el vértice — este es el radio del grafo.
Implementación del algoritmo
Declaramos las constantes y la matriz de pesos del grafo . Una arista ausente se denota con "infinito" INF = \mathrm{0x3F3F3F3F}. Este valor es ciertamente mayor que la longitud de cualquier camino más corto (que no excede 99 \cdot 1000). Al mismo tiempo, la suma de dos infinitos todavía cabe en el tipo , por lo que no se produce desbordamiento al calcular g[i][k] + g[k][j].
#define MAX 110
#define INF 0x3F3F3F3F
int g[MAX][MAX];La función floyd implementa el algoritmo de Floyd — Warshall. El bucle externo itera sobre el vértice intermedio . Para cada par de vértices , verificamos si el camino de a puede acortarse al pasar por el vértice . Si g[i][k] + g[k][j] < g[i][j], actualizamos el valor g[i][j]. Las distancias más cortas se calculan directamente en la matriz .
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 principal del programa. Leemos el número de vértices y la matriz de adyacencia del grafo. El valor significa que no hay arista; lo reemplazamos por .
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;
}Calculamos las distancias más cortas entre todos los pares de vértices. Después de llamar a , el valor g[i][j] es igual a la distancia más corta entre los vértices y .
floyd();Para cada vértice , calculamos su excentricidad — el elemento máximo de la -ésima fila de la matriz . El máximo de todas las excentricidades es igual al diámetro del grafo , y el mínimo es igual al radio 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;
}Imprimimos el diámetro y el radio del grafo.
printf("%d\n%d\n",diam,radius);Implementación en 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();
}
}