天梯杯 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;
}

 

posted on 2018-03-18 21:47  九月旧约  阅读(173)  评论(0编辑  收藏  举报

导航