【Codeforces】 Codeforces Ronda # 606 E. Dos ferias—— 图 论

Enlace de tema

Título

Darle una gráfica no dirigida, averiguar cuántos pares de puntos (x, y) satisfacen que todos los caminos desde el punto x al punto y deben pasar por el punto ay el punto b al mismo tiempo

análisis

Punto único

Primero considere el caso donde el punto ay el punto b son el mismo punto.
Empiezo desde un punto arbitrario, trato todas las rutas conectadas al punto a / b como inexistentes, y atravieso todos los puntos posibles a través de bfs. Entonces estos puntos se pueden conectar sin pasar por el punto a / b.
Por el contrario, si todos los demás puntos pueden ser bfs para formar una estructura de datos similar al conjunto de búsqueda de unión, entonces puedo obtener rápidamente que todos los puntos del conjunto no idéntico deben pasar por el punto a / b.
Próxima pregunta:Cómo asegurarse de que se atraviesan todos los puntos (bfs)
Podemos encontrar constantemente los puntos que no están vis en el arreglo vis y luego continuar con bfs, pero esto es muy ineficiente.
Cambiar otra forma de pensar
Podemos empezar directamente desde el punto a / b, Establezca el punto de partida de bfs como el punto a / b, luego puede completar el recorrido de bfs de todo el gráfico de una vez y guardarlos con una estructura de búsqueda de unión similar.

Dos puntos

Podemos definirlo así.
Si hay un par de puntos (x, y),
asumiendo que la carretera conectada con el punto b se considera desconectada, se satisface que x está conectada con a, pero no está conectada con y.
Al mismo tiempo,
suponiendo que la carretera conectada con el punto a se considera desconectada , Satisface que y y b están conectados, pero no conectados ax.
Entonces podemos obtener el conjunto del punto x y el conjunto del punto y.
Entonces, un punto en cada uno de estos dos conjuntos es un conjunto de pares de puntos razonables

Código AC

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 201000;
const int MAXM = 1001000;

// 无权有向图
struct Graph {
    
    
    struct Edge {
    
    
        int to, next;
    } edge[MAXM];
    int head[MAXN];
    int tot;

    void init(int n) {
    
    
        tot = 0;
        memset(head, -1, sizeof(int) * (n + 1));
    }

    void add_edge(int from, int to) {
    
    
        edge[tot].to = to;
        edge[tot].next = head[from];
        head[from] = tot++;
    }
} graph;


void solve() {
    
    
    int T;
    cin >> T;
    for (int ts = 0; ts < T; ++ts) {
    
    
        int n, m, a, b;
        cin >> n >> m >> a >> b;
        graph.init(n);
        for (int i = 0; i < m; ++i) {
    
    
            int u, v;
            cin >> u >> v;
            graph.add_edge(u, v);
            graph.add_edge(v, u);
        }
        bool vis[MAXN];
        queue<int> q;
        int a_cnt = n - 2, b_cnt = n - 2;

        memset(vis, false, sizeof(bool) * (n + 1));
        q.push(a);
        vis[a] = true;
        while (!q.empty()) {
    
    
            int cur = q.front();
            q.pop();
            for (int i = graph.head[cur]; i != -1; i = graph.edge[i].next) {
    
    
                if (!vis[graph.edge[i].to] && graph.edge[i].to != b) {
    
    
                    vis[graph.edge[i].to] = true;
                    q.push(graph.edge[i].to);
                    a_cnt--;
                }
            }
        }

        memset(vis, false, sizeof(bool) * (n + 1));
        q.push(b);
        vis[b] = true;
        while (!q.empty()) {
    
    
            int cur = q.front();
            q.pop();
            for (int i = graph.head[cur]; i != -1; i = graph.edge[i].next) {
    
    
                if (!vis[graph.edge[i].to] && graph.edge[i].to != a) {
    
    
                    vis[graph.edge[i].to] = true;
                    q.push(graph.edge[i].to);
                    b_cnt--;
                }
            }
        }

        cout << 1ll * a_cnt * b_cnt << endl;
    }
}

int main() {
    
    
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
#ifdef ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    long long test_index_for_debug = 1;
    char acm_local_for_debug;
    while (cin >> acm_local_for_debug) {
    
    
        cin.putback(acm_local_for_debug);
        if (test_index_for_debug > 20) {
    
    
            throw runtime_error("Check the stdin!!!");
        }
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    }
#else
    solve();
#endif
    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/m0_43448982/article/details/103896606
Recomendado
Clasificación