POJ 3177 Rutas redundantes (la cantidad de nuevos bordes que deben crearse para convertirse en un componente de borde con conexión dual)

POJ 3177 Rutas redundantes

Para pasar de uno de los campos de pastoreo F (1 <= F <= 5,000) (que están numerados 1… F) a otro campo, Bessie y el resto del rebaño se ven obligados a cruzar cerca del Árbol de Manzanas Podridas. Las vacas ahora están cansadas de verse obligadas a menudo a tomar un camino en particular y quieren construir algunos caminos nuevos para que siempre tengan la opción de al menos dos rutas separadas entre cualquier par de campos. Actualmente tienen al menos una ruta entre cada par de campos y quieren tener al menos dos. Por supuesto, solo pueden viajar por rutas oficiales cuando se mueven de un campo a otro.
Dada una descripción del conjunto actual de rutas R (F-1 <= R <= 10,000) que cada una conecta exactamente dos campos diferentes, determine el número mínimo de rutas nuevas (cada una de las cuales conecta exactamente dos campos) que deben construirse de manera que que hay al menos dos rutas separadas entre cualquier par de campos. Las rutas se consideran separadas si no usan ninguno de los mismos caminos, incluso si visitan el mismo campo intermedio en el camino.
Puede que ya haya más de una ruta entre el mismo par de campos, y también puede crear una nueva ruta que conecte los mismos campos que alguna otra ruta.


Línea de entrada 1: Dos enteros separados por espacios: F y R
Líneas 2… R + 1: Cada línea contiene dos enteros separados por espacios que son los campos en los puntos finales de alguna ruta.


Línea de salida 1: un único entero que es el número de nuevas rutas que se deben construir.

Conclusión: la cantidad de bordes nuevos necesarios para convertirse en componentes de bordes bi-conectados

Gráfico no dirigido
Cuántas aristas están conectadas para hacer que todo el gráfico no dirigido se convierta en dos caminos completamente diferentes entre dos puntos cualesquiera.

  • Conclusión 1: Hay dos caminos completamente diferentes entre dos puntos => =>=> Sin bordes cortados=> =>=> Gráfico de borde biconectado
  • Conclusión 2: El número de aristas que deben crearse: cnt + 1 2 \ frac {cnt + 1} {2}2c n t + 1 (Redondeado hacia abajo) (donde cnt es el nodo de la hoja del árbol formado al cortar el puente después de que se reducen todos los gráficos de bordes biconectados, es decir, el número de nodos con grado 1)

En primer lugar, podemos reducir los componentes del gráfico conectados por los bordes. Después de reducir el punto, el gráfico se convertirá en un árbol, lo que significa que la ruta entre dos puntos es única. En este momento, el problema se transforma en agregar la menor cantidad de bordes para que
haya al menos dos caminos entre dos puntos cualesquiera en el árbol .

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
typedef long long ll;

const int N = 500007, M = 5000007, INF = 0x3f3f3f3f;

int n, m;
int dfn[N], low[N], num;
int head[N], ver[M], nex[M], edge[M], tot;
int dcc_cnt, cnt;
bool bridge[N];
int dcc_id[N];
int d[N];

void init(){
    
    
    tot = num = cnt = dcc_cnt = 0;
    memset(head, -1, sizeof head);
    memset(dfn, 0, sizeof dfn);
    memset(low, 0, sizeof low);
    memset(bridge, 0, sizeof bridge);
}

void add(int x, int y)
{
    
    
    ver[tot] = y;
    nex[tot] = head[x];
    head[x] = tot ++ ;
}

void tarjan(int x, int in_edge)
{
    
    
    dfn[x] = low[x] = ++ num;
    for(int i = head[x]; ~i; i = nex[i]){
    
    
        int y = ver[i];
        if(!dfn[y]){
    
    
            tarjan(y, i);
            low[x] = min(low[x], low[y]);
            if(dfn[x] < low[y]){
    
    
                bridge[i] = bridge[i ^ 1] = true;
            }
        }
        else if(i != (in_edge ^ 1))
            low[x] = min(low[x], dfn[y]);
    }
}

void dfs(int x)
{
    
    
    dcc_id[x] = dcc_cnt;
    for(int i = head[x] ;~i; i = nex[i]){
    
    
        int y = ver[i];
        if(dcc_id[y] || bridge[i])continue;
        dfs(y);
    }
}

int main()
{
    
    
    while(scanf("%d%d", &n, &m) != EOF){
    
    
        init();
        for(int i = 1; i <= m; ++ i){
    
    
            int x, y;
            scanf("%d%d", &x, &y);
            add(x, y), add(y, x);
        }

        tarjan(1, -1);//整个图是连通的

        for(int i = 1; i <= n; ++ i){
    
    
            if(!dcc_id[i]){
    
    
                ++ dcc_cnt;
                dfs(i);
            }
        }

        for(int i = 0; i < tot; i += 2){
    
    
            if(bridge[i]){
    
    
                int x = ver[i], y = ver[i ^ 1];
                d[dcc_id[x]] ++ ;
                d[dcc_id[y]] ++ ;
            }
        }

        ll cnt = 0;
        for(int i = 1; i <= dcc_cnt; ++ i){
    
    
            if(d[i] == 1)
                cnt ++ ;
        }
        printf("%lld\n", (cnt + 1 ) / 2);
    }
    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/weixin_45697774/article/details/108609352
Recomendado
Clasificación