【ACWing】3556. 最短路径

题目地址:

https://www.acwing.com/problem/content/description/3559/

给定一个 n n n个点 m m m条边构成的无重边和自环的无向连通图。点的编号为 1 ∼ n 1∼n 1n。请问:从 1 1 1 n n n的最短距离。去掉 k k k条边后,从 1 1 1 n n n的最短距离。

输入格式:
第一行包含整数 T T T,表示共有 T T T组测试数据。
每组数据第一行包含三个整数 n , m , k n,m,k n,m,k
接下来 m m m行,每行包含三个整数 x , y , z x,y,z x,y,z,表示点 x x x和点 y y y之间存在一条长度为 z z z的边。
最后一行包含 k k k个空格隔开的整数,表示去掉的边的编号。
所有边按输入顺序从 1 1 1 m m m编号。

输出格式:
每组数据输出占两行。
第一行输出从 1 1 1 n n n的最短距离。
第二行输出去掉 k k k条边后,从 1 1 1 n n n的最短距离。无法到达,则输出 − 1 −1 1

数据范围:
1 ≤ T ≤ 10 1≤T≤10 1T10
1 ≤ n ≤ 50 1≤n≤50 1n50
1 ≤ m ≤ n ( n − 1 ) 2 1≤m≤\frac{n(n−1)}{2} 1m2n(n1)
1 ≤ x , y ≤ n 1≤x,y≤n 1x,yn
1 ≤ z ≤ 100 1≤z≤100 1z100
1 ≤ k ≤ m 1≤k≤m 1km

可以用Dijkstra算法。去掉 k k k条边的时候,直接标记一下那些边不能走即可。代码如下:

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

const int N = 60, INF = 0x3f3f3f3f;
int n, m, k;
int g[N][N], dist[N];
bool vis[N];

int dijkstra() {
  memset(dist, 0x3f, sizeof dist);
  memset(vis, 0, sizeof vis);
  dist[1] = 0;
  for (int i = 0; i < n; i++) {
    int t = -1;
    for (int j = 1; j <= n; j++)
      if (!vis[j] && (!~t || dist[t] > dist[j])) t = j;

    if (t == n) return dist[t] == INF ? -1 : dist[t];
    vis[t] = true;
    for (int j = 1; j <= n; j++)
      if (!vis[j] && ~g[t][j] && dist[j] > dist[t] + g[t][j])
        dist[j] = dist[t] + g[t][j];
  }

  return -1;
}

int main() {
  int T;
  cin >> T;
  while (T--) {
    memset(g, -1, sizeof g);
    scanf("%d%d%d", &n, &m, &k);
    vector<pair<int, int>> es;
    for (int i = 1; i <= m; i++) {
      int a, b, c;
      scanf("%d%d%d", &a, &b, &c);
      g[a][b] = g[b][a] = c;
      es.push_back({a, b});
    }
    printf("%d\n", dijkstra());
    while (k--) {
      int c;
      scanf("%d", &c);
      int x = es[c - 1].first, y = es[c - 1].second;
      g[x][y] = g[y][x] = -1;
    }
    printf("%d\n", dijkstra());
  }
}

每组数据时间复杂度 O ( n 2 ) O(n^2) O(n2),空间 O ( n ) O(n) O(n)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值