PTA L2-001 紧急救援 (点带权最短路)

<题目链接>

题目大意:

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

输入格式:

输入第一行给出4个正整数N、M、S、D,其中N(2)是城市的个数,顺便假设城市的编号为0~(N-1)M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。

第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。

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

解题分析:

由于本题在保证路径最短的情况下,还要使路径上的点权和最大,所以我们在最短路的松弛过程中,优先松弛路径,如果最短路径相同,再考虑挑选点券和最大的路,并且,最短路的条数也能够在Dijkstra松弛的过程中维护。

#include <bits/stdc++.h>
using namespace std;

const int N = 505;
const int INF = 0x3f3f3f3f;
#define pb push_back
int n,m,st,ed;
struct Edge{ int to,val; };
vector<Edge>G[N];      
int path[N],vis[N],num[N];

struct Node{
    int loc,dist,mxval,cnt;
    Node(int _loc=0,int _dist=0,int _mxval=0,int _cnt=0):loc(_loc),dist(_dist),mxval(_mxval),cnt(_cnt){}
    bool operator < (const Node &tmp)const{
        return dist>tmp.dist;
    }
}node[N];

void Dij(){
    memset(path,-1,sizeof(path));
    for(int i=0;i<n;i++){
        vis[i]=0,node[i]=Node(i,INF,0,0);
    }
    priority_queue<Node>q;
    node[st]=Node(st,0,num[st],1);
    q.push(node[st]);
    while(!q.empty()){
        int u=q.top().loc;q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i].to,cost=G[u][i].val;
            if(node[v].dist>node[u].dist+cost){
                node[v].dist=node[u].dist+cost;
                path[v]=u;        //记录上一个点
                node[v].cnt=node[u].cnt;       //更新这个点的最短路条数
                node[v].mxval=node[u].mxval+num[v];    //记录以这个点为终点的最短路的点权和 
                q.push(node[v]);
            }else if(node[v].dist==node[u].dist+cost){    
                node[v].cnt+=node[u].cnt;        //因为有多条最短路径,所以这里将之前的最短路径条数加起来 
                if(node[v].mxval<node[u].mxval+num[v]){       //更新最短路径上的点权最小值 
                    node[v].mxval=node[u].mxval+num[v];
                    path[v]=u;
                }
            }
        }
    }
}

void Print(int u){      //递归打印路径 
    if(u==st){
        printf("%d",st);return;
    }
    Print(path[u]);
    printf(" %d",u);
}

int main(){
    scanf("%d%d%d%d",&n,&m,&st,&ed);
    for(int i=0;i<n;i++)scanf("%d",&num[i]);
    for(int i=0;i<m;i++){
        int u,v,w;scanf("%d%d%d",&u,&v,&w);
        G[u].pb(Edge{v,w});
        G[v].pb(Edge{u,w});
    }
    Dij();
    printf("%d %d\n",node[ed].cnt,node[ed].mxval);
    Print(ed);puts("");
    return 0;
}

 

posted @ 2019-03-21 22:05  悠悠呦~  阅读(388)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end