PAT 1003. Emergency   Dijkstra变形+求相等最短路的数量+特殊权重_最短路

题意:

一个无向图,除了每条路的长度外,每个城市都有个“救援队数量”。

求出相同长度的最短路有多少条。

并求出在这些最短路中, 救援队数量最大的总和。


思路:

用dijkstra,进行一些变形,有些点必须要注意:

(1)最短路条数

当在松弛操作中 “更新”了 长度时,  其j的最短路条数等于 select最短路条数 。

而当长度相等时,注意,j的最短路长度等于  j的最短路条数 加上 select的最短路条数,而不是+1! 因为select那边传递过来的可能不止1条最短路。


(2)救援队数量

每次判断更新就好,这个简单





#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<stack>
#include<vector>
#include<queue>
#include<string>
#include<map>
using namespace std;
#define INF 99999999
#define M 700
int dis[M][M],cost[M][M];
int d[M],c[M],vis[M];
int cityr[M],passr[M],passn[M],city[M];

void disdj(int n,int s,int e)
{
int i,j,select,dmin,rmax;
int pn;
memset(vis,0,sizeof(vis));
for(i = 0;i < n; i++)
{
d[i] = INF;
}
d[s] = 0;
passn[s] = 1;
passr[s] = city[s];
for(i = 0;i < n;i++)
{
select = -1;
dmin = INF;
for(j = 0;j < n;j++)
{
if(vis[j])
continue;
if(d[j] < dmin )
{
dmin = d[j];
select = j;
}
}
if(select == -1 || select == e)
break;
vis[select] = 1;
for(j = 0;j < n; j++)
{
if(vis[j])
continue;
if(d[select] + dis[select][j] < d[j])
{
d[j] = d[select] + dis[select][j];
passn[j] = passn[select];
passr[j] = passr[select] + city[j];
}
else if(d[select] + dis[select][j] == d[j] )
{
passn[j] += passn[select] ;
if(passr[j] < passr[select] + city[j])
{
passr[j] = passr[select] + city[j];
}
}
}
}
printf("%d %d\n",passn[e],passr[e]);
}


int main(){
int n,m,s,e;
scanf("%d%d%d%d",&n,&m,&s,&e);
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
if(i==j)
dis[i][j]=0;
else
dis[i][j]=INF;
}


for(i = 0;i<n;i++)
{
scanf("%d",&city[i]);
}

int re,rs,rl;
for(i=0;i<m;i++)
{
scanf("%d%d%d",&rs,&re,&rl);
dis[rs][re]=dis[re][rs]=rl;
}
disdj(n,s,e);
return 0;
}