2018/6/4
// 题目要求第一个输出是最短路径的个数
// Dijkstra变种
#include <iostream>
#include <climits>
using namespace std;
#define MAXN 500
int n, m, c1, c2;
int city[MAXN][MAXN]; // 各城市间路径
int team[MAXN]; // 各城市队伍数
int road[MAXN]; // 各城市到起点的道路数
int team_max[MAXN]; // 各城市到起点的最大队伍数
int len_min[MAXN]; // 各城市到起点的最短路径长
bool visit[MAXN]; // 该城市是否访问过
void Dijkstra(int start){
fill(visit, visit + n, false);
fill(len_min, len_min + n, INT_MAX);
team_max[start] = team[start];
len_min[start] = 0;
road[start] = 1;
int cur_min;
int u;
for(int i = 0; i < n; i++){
cur_min = INT_MAX;
// 找出到起点最近的点 当 i = 0 时, u就是起点
for(int j = 0; j < n; j++){
if(visit[j] == false && len_min[j] < cur_min){
cur_min = len_min[j];
u = j;
}
}
visit[u] = true;
// 更新其余点到起点的距离
for(int j = 0; j < n; j++){
if(visit[j] == false && city[u][j] != INT_MAX){ // 若INT_MAX定义为0x3f3f3f3f,则可取消判定是否等于INT_MAX,否则不判定的话会超INT范围; 是否判定j访问过都不影响结果
// 若新加入的点u连接其余点后,其余点到起点的距离变短,则更新距离, 路径数为u的路径数
if(len_min[u] + city[u][j] < len_min[j]){
road[j] = road[u];
len_min[j] = len_min[u] + city[u][j];
team_max[j] = team_max[u] + team[j];
// 若相等,则到该点的路径为原有路径加上新加点u的路径
}else if(len_min[u] + city[u][j] == len_min[j]){
road[j] += road[u];
if(team_max[j] < team_max[u] + team[j])
team_max[j] = team_max[u] + team[j];
}
}
}
}
}
int main(){
cin >> n >> m >> c1 >> c2;
for(int i = 0; i < n; i++)
cin >> team[i];
fill(city[0], city[0] + MAXN*MAXN, INT_MAX);
int u, v, len;
for(int i = 0; i < m; i++){
cin >> u >> v >> len;
city[u][v] = city[v][u] = len;
}
Dijkstra(c1);
cout << road[c2] << ' ' << team_max[c2] << endl;
return 0;
}
(2019.3.19)
#include <iostream>
#include <climits>
using namespace std;
#define MAXN 505
int n, m, c1, c2; // city road first_city final_city
int team[MAXN], city[MAXN][MAXN]; // 各城市队伍数 路径图
int dis[MAXN], weight[MAXN], num[MAXN]; // 最短距离 救援人数 最短路径条数
bool visit[MAXN];
int main(){
cin >> n >> m >> c1 >> c2;
for(int i = 0; i < n; i++)
cin >> team[i];
fill(city[0], city[0] + MAXN*MAXN, INT_MAX);
fill(dis, dis + MAXN, INT_MAX);
int u, v, len;
for(int i = 0; i < m; i++){
cin >> u >> v >> len;
city[u][v] = city[v][u] = len;
}
dis[c1] = 0;
weight[c1] = team[c1];
num[c1] = 1;
for(int i = 0; i < n; i++){
int start = -1, cur_min = INT_MAX;
// 找出当前到起点最近的点
for(int j = 0; j < n; j++)
if(visit[j] == false && dis[j] < cur_min){
start = j;
cur_min = dis[j];
}
if(start == -1)
break;
visit[start] = 1;
// 更新其余点到start 的距离
for(int j = 0; j < n; j++){
if(visit[j] == false && city[start][j] != INT_MAX){
if(dis[start] + city[start][j] < dis[j]){
dis[j] = dis[start] + city[start][j];
num[j] = num[start];
weight[j] = weight[start] + team[j];
}else if(dis[start] + city[start][j] == dis[j]){
num[j] += num[start];
if(weight[start] + team[j] > weight[j])
weight[j] = weight[start] + team[j];
}
}
}
}
cout << num[c2] << ' ' << weight[c2] << endl;
return 0;
}