题目:1003. Emergency (25)
解题思路:利用selectnum和maxrescue数组沿途记录下每个点的条数和最大救援队伍数即可(Dijkstra)
#include<stdio.h>
#define MAX 500
#define Inf 99999999
int main()
{
int vernum,arcnum,v1,v2;
int a[MAX][MAX],rescue[MAX],key[MAX],dist[MAX];
int selectnum[MAX],maxrescue[MAX];
int i,j,k;
scanf("%d %d %d %d",&vernum,&arcnum,&v1,&v2);
for(i=0;i<vernum;i++)
{
scanf("%d",&rescue[i]);//初始化城市救援队
key[i]=0;//初始化key数组
for(j=0;j<vernum;j++)
{
if(i==j)a[i][j]=0;
else a[i][j]=Inf;//初始化邻接矩阵
}
}
for(i=0;i<arcnum;i++)//该循环用于读入弧信息
{
int n,m,len;
scanf("%d %d %d",&n,&m,&len);
a[n][m]=len;
a[m][n]=len;
}
for(i=0;i<vernum;i++)dist[i]=a[v1][i];//该循环用于初始化dist数组
for(i=0;i<vernum;i++)//初始化maxrescue和select数组
{
if(a[v1][i]<Inf&&v1!=i)//v1邻接点maxrescue和selectnum初始化
{
maxrescue[i]=rescue[v1]+rescue[i];
selectnum[i]=1;
}
else if(a[v1][i]==Inf)maxrescue[i]=-99;
}
selectnum[v1]=1;
maxrescue[v1]=rescue[v1];
key[v1]=1;//v1收入S集合
int min,v,w;
for(k=0;k<vernum;k++)
{
min=Inf;
for(i=0;i<vernum;i++)//该循环用于找到未被纳入S集合且dist最小的顶点v
{
if(key[i]==0&&dist[i]<min)
{
min=dist[i];
v=i;
}
}
key[v]=1;//v被收入集合S
for(w=0;w<vernum;w++)
{
if(a[v][w]<Inf&&key[w]==0)//对v的每个邻接点w,且w未被访问过
{
if(dist[w]>dist[v]+a[v][w])//小于情况下
{
dist[w]=dist[v]+a[v][w];
maxrescue[w]=maxrescue[v]+rescue[w];//w点的maxrescue为前一个v点的maxrescue+rescue
selectnum[w]=selectnum[v];//前一点v的selectnum
}
else if(dist[w]==dist[v]+a[v][w])//等于情况下,可能路径条数增加,并判定maxrescue大小
{
selectnum[w]+=selectnum[v];//w=w+v;
if(maxrescue[w]<maxrescue[v]+rescue[w])//更新maxrescue数组
maxrescue[w]=maxrescue[v]+rescue[w];
}
}
}
}
printf("%d %d",selectnum[v2],maxrescue[v2]);
return 0;
}