• PAT 天梯赛 L2-1 紧急救援


    Dijkstra算法扩展

    题目链接

    解题代码如下:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #define mt memset
    using namespace std;
    const int inf = 0x3f3f3f3f;
    const int maxn = 510;
    int N,M,S,D;
    int mp[maxn][maxn],team[maxn],dis[maxn],cnt_team[maxn],cnt_road[maxn],pre[maxn];
    //邻接矩阵,每个城市救援队数,源点到各点最短路,源点到各点最大救援队数,源点到各点最短路条数,父节点
    bool vis[maxn];
    void path(int x) {
        if(x == -1)return ;
        if(pre[x] != -1) {
            path(pre[x]);
            cout << " " << x;
        }else {
            cout << x;
        }
    }
    void dijkstra() {
        for(int i = 0; i < N; i++) {
            dis[i] = mp[S][i];
            vis[i] = false;
            pre[i] = (i == S? -1: S);
            if(i != S) {
                if(dis[i] != inf) {
                    cnt_team[i] = team[S] + team[i];
                }else {
                    cnt_team[i] = team[i];
                }
            }else {
                cnt_team[i] = team[S];
            }
            cnt_road[i] = 1;
        }
        vis[S] = true;
        for(int i = 1; i < N; i++) {
            int _min = inf, pos = -1;
            for(int j = 0; j < N; j++) {
                if(!vis[j] && _min > dis[j]) {
                    _min = dis[j];
                    pos = j;
                }
            }
            if(inf == _min || -1 == pos)continue;
            vis[pos] = true;
            for(int j = 0; j < N; j++) {
                if(!vis[j]) {
                    if(dis[j] > dis[pos]+mp[pos][j]) {
                        dis[j] = dis[pos]+mp[pos][j];
                        cnt_road[j] = cnt_road[pos];
                        cnt_team[j] = cnt_team[pos]+team[j];
                        pre[j] = pos;
                    }else if(dis[j] == dis[pos]+mp[pos][j]) {
                        cnt_road[j] = cnt_road[j]+cnt_road[pos];
                        if(cnt_team[j] < cnt_team[pos]+team[j]) {
                            cnt_team[j] = cnt_team[pos]+team[j];
                            pre[j] = pos;
                        }
                    }
                }
            }
        }
        cout << cnt_road[D] << " " << cnt_team[D] << endl;
        path(D);
        cout << endl;
    }
    int main() {
        while(~scanf("%d%d%d%d", &N, &M, &S, &D)) {
            for(int i = 0; i < N; i++) {
                scanf("%d", &team[i]);
            }
            for(int i = 0; i < N; i++) {
                for(int j = 0; j < N; j++) {
                    mp[i][j] = (i == j?0:inf);
                }
            }
            int u,v,w;
            for(int i = 0; i < M; i++) {
                scanf("%d%d%d", &u, &v, &w);
                mp[u][v] = mp[v][u] = w;
            }
            dijkstra();
        }
        return 0;
    }
    

    总结

    这道题目非常适合用来加深理解Dijkstra算法,其中用到的关于到达每个点的最短路路径数目的记录,与计算到达每个点的最大的救援队数目,利用了一些动态规划的思想,十分的巧妙。
    之前打ACM的时候对模板的依赖太多,所以现在要慢慢对每种经典算法进行熟悉理解,争取做到能够手敲,而不是一味的复制粘贴模板。共勉。

    参考资料

    Focus on Tech & Enjoy Life!

  • 相关阅读:
    [bbk3153] 第62集 Chapter 15Application Tuning(02)
    [bbk3152] 第61集 Chapter 15Application Tuning(01)
    [bbk1190]第2集 Chapter 01Oracle Architectural
    PL/SQL高级Creating Packages (01)
    Statspack00
    [bbk3201] 第64集 Chapter 16Using Materialized Views 00
    该如何选择国外VPS
    优化升级logging封装RotatingFileHandler
    smtp ssl模式邮件发送与附件添加
    smtp outlook邮件发送非授权码模式
  • 原文地址:https://www.cnblogs.com/yinzm/p/5492509.html
Copyright © 2020-2023  润新知