#include<iostream>
#include<vector>
const int INT_MAX = 2147483647;
typedef enum { UNDISCOVERED, VISITED }VStatus;//顶点状态,未访问和已访问
template<typename Tv> struct Vertex {//城市
Tv data;//消防队的数量,即顶点的数据
VStatus status;//顶点状态
Vertex(Tv const& d = (Tv)0) :
data(d), status(UNDISCOVERED) {}
};
struct Edge {//路
int weight;//路的长度,即图的权重
Edge(int w) :
weight(w) {}
};
template<typename Tv>
class GraphMatrix {//邻接矩阵
private:
std::vector<Vertex<Tv>> V;//存放顶点,用以访问状态和消防队数量
std::vector<std::vector<Edge*> > E;//存放路的指针,当不联通的时候是nullptr,联通则有指针
public:
int currentCity, mustSavedCity;//我在接到警情时所在的城市,火灾的城市
int miniPath;//最短路径
int miniPathNumber;//最短路径数
int teamNumber;//访问到的路径中团队数
int maxTeamNumber;//最短路径中团队最多数
int n;//结点数
int e;//边数
GraphMatrix() {
n = e = miniPathNumber = teamNumber = currentCity = mustSavedCity = maxTeamNumber = 0;
miniPath = INT_MAX;
}
~GraphMatrix() {
for (int j = 0; j < n; j++)
for (int k = 0; k < n; k++)
delete E[j][k];//逐条清除
}
int firstNbr(int i) {
return nextNbr(i, n);
}
int nextNbr(int i, int j) {//找到i节点在j节点之后的下一个邻居(即存在路径)
while ((-1 < j) && (!exists(i, --j)))
;
return j;
}
int insert(Tv const& vertex) {//插入顶点,返回编号
V.push_back(Vertex<Tv>(vertex));
for (int j = 0; j < n; j++)
E[j].push_back(nullptr);
++n;
E.push_back(std::vector<Edge*>(n,nullptr));
return n;
}
bool exists(int i, int j) {
return (-1 < i) && (i < n) && (-1 < j) && (j < n) && (E[i][j] != nullptr);
}
void insert(int w, int i, int j) {//插入边的指针
if (exists(i, j))
return;
E[i][j] = new Edge(w);
++e;
}
void DFS(int currentCity,int destination) {
if (miniPath < destination)//当前路程比曾经最小路程长,舍弃该路径
return;
if (currentCity == mustSavedCity) {//找到节点
teamNumber += V[currentCity].data;//加上目标城市的消防队数量
if (destination < miniPath) {//找到新的最短路径,更新路径数量为一,更新消防队数量为当前路径数量
miniPath = destination;
miniPathNumber = 1;
maxTeamNumber = teamNumber;
}
else if (destination == miniPath) {//找到另一条最短路径,路径数量加一,更新最大消防队数量
miniPathNumber++;
if (maxTeamNumber < teamNumber)
maxTeamNumber = teamNumber;
}
teamNumber -= V[currentCity].data;//退出目标城市,消防队数量为父节点的消防队数量
return;
}
for (int w = firstNbr(currentCity); -1 < w; w = nextNbr(currentCity, w)) {//依次访问当前城市的邻居,一条路一条路找,看是否能到达目标城市
V[currentCity].status = VISITED;//将当前城市设置为已访问,避免递归调用DFS()时重新访问当前节点,造成环路
teamNumber += V[currentCity].data;//加上当前城市的消防队数量
if (V[w].status == UNDISCOVERED)
DFS(w, destination + E[currentCity][w]->weight);//递归调用DFS()函数,用来不断寻找下一个节点,判断下一个节点是不是目标节点
V[currentCity].status = UNDISCOVERED;//退出当前城市
teamNumber -= V[currentCity].data;//退出当前城市,消防队数量为父节点的消防队数量
}
}
};
int main() {
GraphMatrix<int> map;
int n, e;
scanf("%d", &n);
scanf("%d", &e);
scanf("%d %d", &(map.currentCity), &(map.mustSavedCity));
for (int i = 0,temp; i < n; ++i) {
scanf("%d", &temp);
map.insert(temp);
}
for (int k = 0, w, i, j; k < e; ++k) {
scanf("%d %d %d", &i, &j, &w);
map.insert(w, i, j);//2、5测试点一直错的原因 邻接矩阵的存储是关于斜对角线对称的
map.insert(w, j, i);
}
map.DFS(map.currentCity, 0);
printf("%d %d\n", map.miniPathNumber, map.maxTeamNumber);
return 0;
}
二刷