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
#include
#include
#include
#include
#include
#include
#include
#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

 

 

 

 

你可能感兴趣的:(pat甲级)