zoukankan      html  css  js  c++  java
  • 天梯杯 PAT L2-001. 紧急救援 最短路变形

    作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。

    输入格式:

    输入第一行给出4个正整数N、M、S、D,其中N(2<=N<=500)是城市的个数,顺便假设城市的编号为0~(N-1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。

    输出格式:

    第一行输出不同的最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出首尾不能有多余空格。

    输入样例:

    4 5 0 3
    20 30 40 10
    0 1 1
    1 3 2
    0 3 3
    0 2 2
    2 3 2
    

    输出样例:

    2 60
    0 1 3

    emmmm,图论一直是弱项,简单的最短路变形一直挺模糊的无从下手,这道题值得好好学习。其实写了以后还是比较好懂的。
    #include<queue>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    #define maxn 510
    #define debug(a) cout << #a << " " << a << endl
    //val每个城市紧急救援队的数量,re代表最短路中紧急队最多的那条路径经过的点,vis判断当前点是否走过
    //total代表每个点的最短路中的紧急队最多的数量,pathnum代表当前点的最短路径的数量
    //dis代表路径长度,path记录当前点的前驱
    int n,m,s,d,val[maxn],mapn[maxn][maxn],re[maxn],vis[maxn];
    int total[maxn],pathnum[maxn],dis[maxn],path[maxn];
    void dijkstra( int v0 ) {
        for( int i = 0; i < n; i ++ ) {
            dis[i] = 1e9;
        }
        vis[v0] = true;
        dis[v0] = 0;
        total[v0] = val[v0];
        pathnum[v0] = 1;
        for( int i = 0; i < n; i ++ ) {
            if( mapn[v0][i] != 1e9 && i != v0 ) {
                dis[i] = mapn[v0][i];
                path[i] = v0;
                total[i] = val[v0] + val[i];
                pathnum[i] = 1;
            }
        }
        for( int i = 0; i < n - 1; i ++ ) {
            int minn = 1e9, mival = 0, u = v0;
            for( int j = 0; j < n; j ++ ) {
                if( !vis[j] && dis[j] < minn ) {
                    minn = dis[j];
                    u = j;
                }
            }
            vis[u] = true;
            for( int j = 0; j < n; j ++ ) {
                if( !vis[j] ) {
                    if( dis[u] + mapn[u][j] < dis[j] ) {
                        pathnum[j] = pathnum[u];
                        dis[j] = dis[u] + mapn[u][j];
                        total[j] = total[u] + val[j];
                        path[j] = u;
                    } else if( dis[u] + mapn[u][j] == dis[j] ) {
                        pathnum[j] += pathnum[u];
                        if( total[j] < total[u] + val[j] ) {
                            total[j] = total[u] + val[j];
                            path[j] = u;
                        }
                    }
                }
            }
        }
    }
    int main() {
        while( cin >> n >> m >> s >> d ) {
            for( int i = 0; i < n; i ++ ) {
                cin >> val[i];
            }
            for( int i = 0; i < n; i ++ ) {
                for( int j = 0; j < n; j ++ ) {
                    mapn[i][j] = 1e9;
                }
            }
            int x,y,l;
            for( int i = 0; i < m; i ++ ) {
                cin >> x >> y >> l;
                mapn[x][y] = min( mapn[x][y], l );
                mapn[y][x] = mapn[x][y];
            }
            dijkstra( s );
            int num = 0, cur = d;
            while( cur != s ) {
                re[num++] = cur;
                cur = path[cur];
            }
            re[num++] = s;
            cout << pathnum[d] << " " << total[d] << endl;
            for( int i = num - 1; i > 0; i -- ) {
                cout << re[i] << " ";
            }
            cout << re[0] << endl;
        }
        return 0;
    }
    彼时当年少,莫负好时光。
  • 相关阅读:
    POJ 3630 Phone List/POJ 1056 【字典树】
    HDU 1074 Doing Homework【状态压缩DP】
    POJ 1077 Eight【八数码问题】
    状态压缩 POJ 1185 炮兵阵地【状态压缩DP】
    POJ 1806 Manhattan 2025
    POJ 3667 Hotel【经典的线段树】
    状态压缩 POJ 3254 Corn Fields【dp 状态压缩】
    ZOJ 3468 Dice War【PD求概率】
    POJ 2479 Maximum sum【求两个不重叠的连续子串的最大和】
    POJ 3735 Training little cats【矩阵的快速求幂】
  • 原文地址:https://www.cnblogs.com/l609929321/p/8597714.html
Copyright © 2011-2022 走看看