7-7 Super Mario (10 puntos)

Suponga que hay n castillos, numerados del 1 al N. Algunos castillos están conectados directamente por carreteras y otros no están conectados directamente por carreteras. Mario ahora va a ir de un castillo a otro, tiene una varita mágica que puede pasar por un camino instantáneamente, es decir, pasar este camino en 0 tiempo, pero la varita mágica solo se puede usar una vez. Mario quiere llegar al destino en el menor tiempo posible, por favor escriba un programa para elegir una ruta para Mario y dónde usar la varita mágica. Suponiendo que todas las carreteras sean de doble sentido, se garantiza que se puede llegar al destino desde el punto de partida.

Inserte la descripción de la imagen aquí
Formato de entrada:
ingrese la primera línea de 4 números enteros n, s, t, m, que representan respectivamente el número de castillos (numerados del 1 al n, n no excede 10000), el punto de inicio s donde está Mario y el punto final t al que quieres ir, entre los castillos El número de carreteras. En las siguientes m líneas, cada línea contiene 3 números enteros positivos a, byc, lo que indica que hay un camino conectado directamente entre el castillo ay el castillo b, y se necesitan c minutos para pasar el camino.

Formato de salida: La
salida son dos números enteros separados por espacios. El primer número entero es el tiempo más corto requerido para que Mario llegue desde el punto de inicio al destino; el segundo número entero representa el lugar donde se usa la varita mágica, es decir, el castillo número, si hay más de uno posible, entonces se emitirá el que tenga el número más pequeño.

Muestra de entrada:

4 1 4 4
1 2 9
2 4 1
1 3 3
3 4 5

Salida de muestra:

1 1

Estuve atrapado en el rango de datos de los dos últimos puntos de prueba durante mucho tiempo. No se hace de forma independiente, pregunte a los demás
Código de CA 1: Encuentre el camino más corto de sy el camino más corto de t una vez, y luego enumere los bordes. Si los dos puntos finales de este borde pueden alcanzar syt respectivamente, significa que hay un camino por recorrer desde s t a través de este borde. Entonces el valor mínimo de esta ruta es la ruta más corta desde sa un extremo de este lado + t la ruta más corta hasta el otro extremo. Es necesario recordar esta lista de adyacencia e inicialización, porque rara vez escribo esto, pero he visto
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;

typedef struct {
    
    
    int u, v; //每条边的起点和终点
} Edge;

typedef long long ll;
const ll inf = 1e12;
const int N = 1e4 + 10, M = 1e8 + 10;//分别为顶点数和边数
bool vis[N] = {
    
    false};
ll diss[N], dist[N]; //diss表示起点s到其他各点的距离,dist表示终点t到其他各点的距离
 //h表示从某顶点出发的第一条边的编号,e为该条边的终点编号,
 //w为该条边的权值,ne存储从该顶出发的下一条边的编号,idx为第几条边
int h[N], e[M], w[M], ne[M], idx;
int n, m, s, t; //顶点数 边数 起点 终点
Edge edge[M]; //存储每一条边的信息

void add(int a, int b, int c) {
    
     //邻接表(头插法)存储边信息
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}

void spfa(ll dis[], int u) {
    
     //最短路算法spfa
    for (int i = 1; i <= n; i++) {
    
    
        dis[i] = inf;
        vis[i] = false;
    }
    queue<int> qe;
    qe.push(u);
    dis[u] = 0;
    vis[u] = true;
    while (!qe.empty()) {
    
    
        int x = qe.front();
        qe.pop();
        vis[x] = false;
        for (int i = h[x]; i != -1; i = ne[i]) {
    
    
            int j = e[i];
            if (dis[j] > dis[x] + w[i]) {
    
    
                dis[j] = dis[x] + w[i];
                if (!vis[j]) {
    
    
                    qe.push(j);
                    vis[j] = 1;
                }
            }
        }
    }
}

int main() {
    
    
    scanf("%d %d %d %d", &n, &s, &t, &m);
    memset(h, -1, sizeof(h)); //初始时,每个顶点的第一条边的编号都设为-1,表示没有边
    for (int i = 0; i < m; i++) {
    
     //输入每条边的信息
        int a, b, c;
        scanf("%d %d %d", &a, &b, &c);
        add(a, b, c), add(b, a, c); //双向存储边信息
        edge[2 * i].u = a, edge[2 * i].v = b;//正向存储每条边的起点和终点
        edge[2 * i + 1].u = b, edge[2 * i + 1].v = a;//反向存储每条边的起点和终点
    }
    spfa(diss, s);//从起点s出发的单源最短路
    spfa(dist, t);//从终点t出发的单源最短路
    ll minx = inf;
    int pos;
    for (int i = 0; i < 2 * m; i++) {
    
    
        int a = edge[i].u, b = edge[i].v;
        if (diss[a] + dist[b] < minx) {
    
     //寻找最小值
            minx = diss[a] + dist[b];
            pos = a;
        } else if (diss[a] + dist[b] == minx && a < pos) {
    
     //最小值相同时,寻找最小编号
            pos = a;
        }
    }
    printf("%lld %d", minx, pos);
    return 0;
}
Versión de idioma Code 1C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    
    
    int u, v; //每条边的起点和终点
} Edge;

typedef long long ll;
const ll inf = 1e12;
//M的大小不能为1e8及以上,我的不行,提示内存超限!!!!
const int N = 1e4 + 10, M = 1e7 + 1000; //分别为顶点数和边数
int q[N];
int vis[N] = {
    
    0};
ll diss[N],
    dist[N]; // diss表示起点s到其他各点的距离,dist表示终点t到其他各点的距离
             // h表示从某顶点出发的第一条边的编号,e为该条边的终点编号,
             // w为该条边的权值,ne存储从该顶出发的下一条边的编号,idx为第几条边
int h[N], e[M], w[M], ne[M], idx;
int n, m, s, t; //顶点数 边数 起点 终点
Edge edge[M];   //存储每一条边的信息

void add(int a, int b, int c) {
    
     //邻接表(头插法)存储边信息
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}

void spfa(ll dis[], int u) {
    
     //最短路算法spfa
    for (int i = 1; i <= n; i++) {
    
    
        dis[i] = inf;
        vis[i] = 0;
    }
    int head = 0, rear = 0;
    q[rear++] = u;
    dis[u] = 0;
    vis[u] = 1;
    while (head != rear) {
    
    
        int x = q[head++];
        vis[x] = 0;
        for (int i = h[x]; i != -1; i = ne[i]) {
    
    
            int j = e[i];
            if (dis[j] > dis[x] + w[i]) {
    
    
                dis[j] = dis[x] + w[i];
                if (!vis[j]) {
    
    
                    q[rear++] = j;
                    vis[j] = 1;
                }
            }
        }
    }
}

int main() {
    
    
    scanf("%d %d %d %d", &n, &s, &t, &m);
    memset(h, -1,sizeof(h)); //初始时,每个顶点的第一条边的编号都设为-1,表示没有边
    for (int i = 0; i < m; i++) {
    
     //输入每条边的信息
        int a, b, c;
        scanf("%d %d %d", &a, &b, &c);
        add(a, b, c), add(b, a, c);           //双向存储边信息
        edge[2 * i].u = a, edge[2 * i].v = b; //正向存储每条边的起点和终点
        edge[2 * i + 1].u = b, edge[2 * i + 1].v = a; //反向存储每条边的起点和终点
    }
    spfa(diss, s); //从起点s出发的单源最短路
    spfa(dist, t); //从终点t出发的单源最短路
    ll minx = inf;
    int pos;
    for (int i = 0; i < 2 * m; i++) {
    
    
        int a = edge[i].u, b = edge[i].v;
        if (diss[a] + dist[b] < minx) {
    
     //寻找最小值
            minx = diss[a] + dist[b];
            pos = a;
        } else if (diss[a] + dist[b] == minx && a < pos) {
    
     //最小值相同时,寻找最小编号
            pos = a;
        }
    }
    printf("%lld %d", minx, pos);
    return 0;
}
Código AC 2: Gráfico jerárquico, emmm, todavía es muy incómodo, después de la finalización, un total de dos gráficos, usando el algoritmo de ruta más corta una vez, no el código que escribí.
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int path[N], h[N], e[N], w[N], ne[N], idx, d[N], q[N], n;
bool st[N];
void add(int a, int b, int c) {
    
    
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
void spfa(int s) {
    
    
    memset(d, 0x3f, sizeof d);
    int hh = 0, tt = 0;
    q[tt++] = s;
    d[s] = 0;
    st[s] = 1;
    while (hh != tt) {
    
    
        int t = q[hh++];
        st[t] = 0;
        for (int i = h[t]; ~i; i = ne[i]) {
    
    
            int j = e[i];
            if (d[j] > d[t] + w[i]) {
    
    
                d[j] = d[t] + w[i];
                path[j] = t;
                if (!st[j]) {
    
    
                    q[tt++] = j;
                    st[j] = 1;
                }
            } else if (n <= 10 && d[j] == d[t] + w[i] && path[j] > t)
                path[j] = t;
        }
    }
}
int main() {
    
    
    memset(h, -1, sizeof h);
    int s, t, m;
    scanf("%d%d%d%d", &n, &s, &t, &m);
    while (m--) {
    
    
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c), add(b, a, c), add(a, b + n, 0), add(b, a + n, 0),
            add(a + n, b + n, c), add(b + n, a + n, c);
    }
    spfa(s);
    int x = t + n;
    while (x > n)
        x = path[x];
    printf("%d %d", d[t + n], x);
    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/weixin_45845039/article/details/113743152
Recomendado
Clasificación