Algoritmos de Grafos: Cálculo de Distâncias Médias, Minimização de Ruído e Identificação de Pontes Críticas

Page Hopping - UVA 821

Em um ambiente com N salas interconectadas (1≤N≤100), calculamos a distância média dos caminhos mais curtos entre todos os pares de salas alcençáveis. A entrada consiste em múltiplos casos de teste terminados com "0 0". Para cada caso, pares de inteiros indicam conexões diretas entre salas.

#include <iostream>
#include <climits>
#include <iomanip>
using namespace std;

const int LIMITE = 101, INF = INT_MAX;

int matriz[LIMITE][LIMITE];
int maiorID;

void preencherMatriz() {
    for(int i = 1; i <= maiorID; i++) {
        for(int j = 1; j <= maiorID; j++) {
            matriz[i][j] = (i == j) ? 0 : INF;
        }
    }
}

void executarFloyd() {
    for(int k = 1; k <= maiorID; k++) {
        for(int i = 1; i <= maiorID; i++) {
            if(matriz[i][k] == INF) continue;
            for(int j = 1; j <= maiorID; j++) {
                if(matriz[k][j] != INF) {
                    matriz[i][j] = min(matriz[i][j], matriz[i][k] + matriz[k][j]);
                }
            }
        }
    }
}

int main() {
    int origem, destino, caso = 1;
    cout << fixed << setprecision(3);
    
    while(cin >> origem >> destino, origem || destino) {
        maiorID = 0;
        preencherMatriz();
        
        do {
            maiorID = max(maiorID, max(origem, destino));
            matriz[origem][destino] = 1;
        } while(cin >> origem >> destino, origem || destino);
        
        executarFloyd();
        double soma = 0;
        int conexoes = 0;
        
        for(int i = 1; i <= maiorID; i++) {
            for(int j = 1; j <= maiorID; j++) {
                if(i != j && matriz[i][j] != INF) {
                    soma += matriz[i][j];
                    conexoes++;
                }
            }
        }
        cout << "Caso " << caso++ << ": comprimento médio = " << soma/conexoes << " cliques\n";
    }
    return 0;
}

Audiophobia

Determinamos a intensidade sonora mínima máxima necessária para percorrer caminhos entre pares de pontos em um grafo. Cada consulta requer encontrar o menor valor máximo de arestas em qualquer caminho entre dois nós.

#include <iostream>
#include <algorithm>
using namespace std;

const int TAM = 101, LIM = 0x3f3f3f3f;

int grafo[TAM][TAM];
int vertices, arestas, consultas;

void configurarGrafo() {
    for(int i = 1; i <= vertices; i++) {
        fill(grafo[i], grafo[i] + vertices + 1, LIM);
        grafo[i][i] = 0;
    }
}

void processarCaminhos() {
    for(int k = 1; k <= vertices; k++) {
        for(int i = 1; i <= vertices; i++) {
            for(int j = 1; j <= vertices; j++) {
                grafo[i][j] = min(grafo[i][j], max(grafo[i][k], grafo[k][j]));
            }
        }
    }
}

int main() {
    int teste = 1;
    while(cin >> vertices >> arestas >> consultas, vertices) {
        configurarGrafo();
        while(arestas--) {
            int a, b, decibeis;
            cin >> a >> b >> decibeis;
            grafo[a][b] = grafo[b][a] = min(grafo[a][b], decibeis);
        }
        processarCaminhos();
        if(teste > 1) cout << "\n";
        cout << "Caso #" << teste++ << "\n";
        while(consultas--) {
            int partida, chegada;
            cin >> partida >> chegada;
            if(grafo[partida][chegada] == LIM) {
                cout << "sem caminho\n";
            } else {
                cout << grafo[partida][chegada] << "\n";
            }
        }
    }
}

As Pontes de Caocao

Identificamos a ponte crítica de menor peso em uma rede de ilhas. A remoção dessa ponte desconecta o grafo, com restrições especiais para pesos zero ou ausência de soluções.

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAX_NOS = 1010, MAX_ARESTAS = 2000010, INF = 0x3f3f3f3f;

int listaAdj[MAX_NOS], prox[MAX_ARESTAS], alvo[MAX_ARESTAS], peso[MAX_ARESTAS];
int registro[MAX_NOS], baixo[MAX_NOS];
int contador, tempo, melhor;
bool ponte[MAX_ARESTAS];

void inicializar(int nos) {
    memset(listaAdj, -1, sizeof(int) * (nos + 1));
    memset(registro, 0, sizeof(int) * (nos + 1));
    contador = tempo = 0;
    melhor = INF;
}

void adicionarAresta(int a, int b, int w) {
    alvo[contador] = b;
    peso[contador] = w;
    prox[contador] = listaAdj[a];
    listaAdj[a] = contador++;
}

void tarjan(int no, int arestaAnterior) {
    registro[no] = baixo[no] = ++tempo;
    for(int i = listaAdj[no]; ~i; i = prox[i]) {
        int viz = alvo[i];
        if(!registro[viz]) {
            tarjan(viz, i ^ 1);
            baixo[no] = min(baixo[no], baixo[viz]);
            if(baixo[viz] > registro[no]) {
                melhor = min(melhor, peso[i]);
            }
        } else if(i != arestaAnterior) {
            baixo[no] = min(baixo[no], registro[viz]);
        }
    }
}

int main() {
    int totalIlhas, totalPontes;
    while(cin >> totalIlhas >> totalPontes, totalIlhas) {
        inicializar(totalIlhas);
        while(totalPontes--) {
            int u, v, guardas;
            cin >> u >> v >> guardas;
            adicionarAresta(u, v, guardas);
            adicionarAresta(v, u, guardas);
        }
        int componentes = 0;
        for(int i = 1; i <= totalIlhas; i++) {
            if(!registro[i]) {
                tarjan(i, -1);
                componentes++;
            }
        }
        if(componentes > 1) {
            cout << "0\n";
        } else if(melhor == INF) {
            cout << "-1\n";
        } else if(melhor == 0) {
            cout << "1\n";
        } else {
            cout << melhor << "\n";
        }
    }
}

Tags: floyd-warshall Tarjan Grafos ponte caminhos-minimos

Publicado em 7-14 18:47