1003 Emergency (25分)

原题链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805523835109376

题意求最短路有多少条,其中经过救援队最多的数量是多少。

思路:如何计算最短路有多少条?并且经过的最短路中救援队伍最多?dijkstra是通过已知子集中的元素去找和子集元素最近的一条,并把该点加入子集,然后通过该点到达目的地更近还是直接到达更近。所以我们能做的就是判断这个中间点k和目的地j。第一种情况是dis[j] == dis[k]+e[k][j],这种意味着从k到j和直接到j距离一样,所以最短路数量等于从原点到j加上从原点到k的条数,这里使用tot[maxn]来表示,tot]j]表示目的地为j的最短路条数。第二种情况是dis[j] > dis[k]+e[k][j],表示从k到j比直接到达j更近,所以tot[j]=tot[k],直接把k存在的最短路赋值给j。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<cmath>
#include<set>
#define ll long long
using namespace std;
const int N=505,INF=0x3f3f3f3f;

int a[N],e[N][N];
int vis[N],dis[N],tot[N],num[N]; //tot表示最短路条数,num表示经过的救援队数量
int n,m,c1,c2;
 
void dijk()
{
    for(int i = 0;i < n;++i) dis[i] = e[c1][i];
    
    num[c1] = a[c1];
    tot[c1] = 1;
    for(int i = 0;i < n;++i)
    {
    	int minor = INF;
    	int k;
    	for(int j = 0;j < n;++j)
    	{
    		if(!vis[j] && dis[j] < minor)
    		{
    			minor = dis[j];
    			k = j;
    		}
    	}
    	vis[k] = 1; 
    	for(int j = 0;j < n;++j)
    	{
    		if(vis[j]) continue;
            if(dis[j] == dis[k]+e[k][j])
    		{
    			tot[j] += tot[k];
    			num[j] = max(num[j],num[k]+a[j]);
    		}
    		if(dis[j] > dis[k]+e[k][j])
    		{
    			dis[j] = dis[k]+e[k][j];
    			tot[j] = tot[k];
    			num[j] = num[k]+a[j];
    		}
    		
    	}
    }
}
 
int main(){
	
    scanf("%d%d%d%d",&n,&m,&c1,&c2);
    
    for(int i=0;i<n;i++)
	{
        scanf("%d",&a[i]);
    }
    for(int i=0;i<n;i++)
	{
        for(int j=0;j<n;j++)
		{
            if(i==j)  e[i][j]=0;
            else e[i][j]=INF;
        }
    }
    int s,ed,c;
    while(m--){
        scanf("%d%d%d",&s,&ed,&c);
        e[s][ed]=c;
        e[ed][s]=c;
    }
    dijk();
    printf("%d %d\n",tot[c2],num[c2]);
}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值