Dijkstra 天梯赛L2

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

输入格式:

输入第一行给出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

 本来第一反应是用迪杰斯特拉加上优先队列的,但是我总是用不好优先队列。(只会BFS的优先队列) 其实这道题用优先队列的很好做的 ,有时间再去研究一下。

因为要存储最短路的所有路径,所以要开个数组存下来。然后就是并查集的搜索,说白了就是递归调用

#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <stdio.h>
#include <ctype.h>
#include <bitset>
#define LL long long
#define ULL unsigned long long
#define mod 1000000007
#define INF 0x3ffffff
#define mem(a,b) memset(a,b,sizeof(a))
#define MODD(a,b) (((a%b)+b)%b)
#define PI 3.1415927
#define maxn 1000
using namespace std;
int N,M,S,D;
int val[maxn],dis[maxn],vis[maxn],cnt[maxn],sum[maxn],pre[maxn];
int mp[maxn][maxn];
void findfa(int x)
{
    if(pre[x] != -1){
        findfa(pre[x]);
        printf("%d ",pre[x]);
    }
}
void Dijkstra(int S)
{
   // vis[S] = 1;
    dis[S] = 0;
    cnt[S] = 1;
    sum[S] = val[S];
    for(int i = 0;i < N; i++){
        int u = -1 , Min = INF;
        for(int j = 0; j < N; j++){
            if(vis[j] == 0 && dis[j] < Min){
                u = j;
                Min = dis[j];
            }
        }
        if(u == -1) return ;
        vis[u] = 1;
        for(int v = 0; v < N; v++){
            if(vis[v] == 0 && mp[u][v] != INF && dis[u] + mp[u][v] < dis[v]){
                dis[v] = dis[u] + mp[u][v];
                sum[v] = sum[u] + val[v];
                cnt[v] = cnt[u];
                pre[v] = u;
            }
            else if(dis[u] + mp[u][v] == dis[v]){//发现路径相等的,总数++
                cnt[v] = cnt[v] + cnt[u];
                if(sum[v] < sum[u] + val[v]){发现救援队可以增加的 就更新
                    sum[v] = sum[u] + val[v];
                    pre[v] = u;
                }
            }
        }
    }

}

int main()
{
    scanf("%d%d%d%d",&N,&M,&S,&D);
    for(int i=0;i<N;i++) scanf("%d",&val[i]);
    fill(mp[0],mp[0]+maxn*maxn,INF);
    for(int i=0;i<M;i++){
       int a,b,c;
       scanf("%d%d%d",&a,&b,&c);
       mp[a][b] = c;
       mp[b][a] = c;
    }
    fill(dis,dis+N,INF);
    mem(vis,0);
    mem(cnt,0);
    mem(sum,0);
    mem(pre,-1);
    Dijkstra(S);
    //for(int i = 0; i < N ;i++) printf("--%d--",dis[i]);
    printf("%d %d\n",cnt[D],sum[D]);

    /*for(int i = 0;i < N ;i++){
        if(pre[i] != -1)
        printf("%d ",pre[i]);
    }*/
    findfa(D);
    printf("%d\n",D);





    return 0;

}

猜你喜欢

转载自blog.csdn.net/qq_40620465/article/details/88876402