PAT 1003 Emergency (25 分)

1003 Emergency (25 分)

今天分享的是PAT甲级的一道小题,是一道经典的回溯剪枝的问题

原题请点击我

简单翻译:

给你一个无向图,一共N个节点M条边,每个节点对应一个权重,节点之间的边有路径的长度,求从其中的c1节点到c2节点一共有多少种最短路径,这些路径所经历的节点的最大权重是多少。

思路:

最开始的思路是Dijkstra,后来发现没有必要使用Dijkstra,就是一个回溯+剪枝的应用。

从根节点出发,有路径就开始走,并维护当前的状态,如果某个点没有走过,并且与当前的点存在连线的话,就走那个节点

如果当前节点已经是目的节点了,那么就开始维护需要的值

  • 判断是不是最短路径
    • 如果比当前最短的还要短,就更新当前最短路径的条数为1,并且权重直接赋值为当前的权重
    • 如果和当前的路径一样短,就将最短路径的条数 + 1,并且维护当前的权重,取最大值。
    • 相反则直接忽略。

这样通过暴力的遍历+部分剪枝,就可以通过这道题,算是一道经典的问题了。

c++代码:

#include"bits/stdc++.h"
#define all(x) x.begin(),x.end()
#define len(x) x.size()
#define INF (1e9)
#define vi vector<int>
#define ll long long
#define db double
#define vvi vector<vector<int>>
#define pb(x) push_back(x);
using namespace std;
vvi grid(501, vi(501, 0));
vi vis(501, 0);
vi num(501, 0);
int n, m, c1, c2;
int cnt = 0, people = -INF, minRoad = INF;
void dfs(int now, int peo, int road) {
    if (now == c2) {
        if (road == minRoad) {
            minRoad = road;
            people = max(people, peo);
            cnt++;
        }
        if (road < minRoad) {
            minRoad = road;
            people = peo;
            cnt = 1;
        }
        return;
    }
    for (int i = 0; i < n; i++) {
        if (grid[now][i] > 0 && vis[i] == 0) {
            vis[i] = 1;
            dfs(i, peo + num[i], road + grid[now][i]);
            vis[i] = 0;
        }
    }
}
int main() {
    cin >> n >> m >> c1 >> c2;
    for (int i = 0; i < n; i++) {
        cin >> num[i];
    }
    for (int i = 0; i < m; i++) {
        int temp1, temp2, temp3;
        cin >> temp1 >> temp2 >> temp3;
        grid[temp1][temp2] = temp3;
        grid[temp2][temp1] = temp3;
    }
    dfs(c1, num[c1], 0);
    cout << cnt << " " << people;

    return 0;
}

点我看PAT甲级的全部题解

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值