Sample Input
5 6 0 2 1 2 1 5 3 0 1 1 0 2 2 0 3 1 1 2 1 2 4 1 3 4 1
Sample Output
2 4
#include <iostream>
using namespace std;
#define INF 1000000
int Graph[500][500];
int TeamNum[500]; // 每个城市拯救队伍数目
int s[500]; // 判断是否已存入该点到S集合中
int Dist[500]; // 从v0到vi的最短路径长度
int TotalTeamNum[500]; // 从v0到k的拯救队伍数
int path[500]; // 最短路径的数目
void dijkstra(int v0, int N)
{
for(int i = 0; i < N; i++) //初始化
{
Dist[i] = Graph[v0][i];
s[i] = 0; // 初始都未用过该点
TotalTeamNum[i] = TeamNum[v0] + TeamNum[i];
path[i] = 1;
}
// 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
// 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
// 注意是从第二个节点开始,第一个为源点
s[v0] = 1; //v0加入到顶点集合S
Dist[v0] = 0;
TotalTeamNum[v0] = TeamNum[v0];
for(int i = 0; i < N; i++)
{
int min = INF, u = v0;
for(int j = 0; j < N; j++)
{
// 找出当前未使用的点j的dist[j]最小值
// u保存当前邻接点中距离最小的点的号码
if(!s[j] && Dist[j] < min)
{
u = j;
min = Dist[j];
}
}
s[u] = 1; //将u加入到集合S中
// 更新dist
for(int k = 0; k < N; k++)
{
if(!s[k] && Graph[u][k] < INF && Dist[u] + Graph[u][k] < Dist[k])
{
Dist[k] = Dist[u] + Graph[u][k];
TotalTeamNum[k] = TotalTeamNum[u] + TeamNum[k];
path[k] = path[u];
}
else if(!s[k] && Graph[u][k] < INF && Dist[u] + Graph[u][k] == Dist[k])
{
if(TotalTeamNum[k] < TotalTeamNum[u]+TeamNum[k]) //更新最大值
{
TotalTeamNum[k] = TotalTeamNum[u]+TeamNum[k];
}
path[k] = path[u] + path[k];
}
}
}
}
int main()
{
int N,M,C1,C2;
cin>>N>>M>>C1>>C2;
for(int i = 0; i < N; i++)
{
cin>>TeamNum[i];
}
for(int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
{
if(i == j)
{
Graph[i][j]=0;
}
else
{
Graph[i][j]=INF;
}
}
}
for(int i = 0; i < M; i++)
{
int a,b,c;
cin>>a>>b>>c;
Graph[a][b]=Graph[b][a]=c;
}
dijkstra(C1,N);
cout<<path[C2]<<" "<<TotalTeamNum[C2];
return 0;
}