#include<iostream> #include<cstring> using namespace std; const int N = 1000; const int INF = 100000000; //图的邻接矩阵 int road[N][N]; //标记某一节点是否被访问过 bool isVisited[N]; //记录每一节点的权值 int team_num[N]; int dis[N]; //最短路径的数目 int path_num =0; //最大的医疗队的数目 int g_max_team_num = 0; void initData() { int i,j; for(i=0; i<N; i++) { isVisited[i] = false; team_num[i] = 0; dis[i] = INF;//初始化为无穷大. for(j=0; j<N; j++) { road[i][j] = INF; road[j][i] = INF; } } } //单源最短路径算法。 void Dijstra(int n,int src, int des) { int i,j; for(i=0; i<n; i++) dis[i] = road[src][i]; isVisited[src] = true; for(i=0; i<n-1; i++)//最多循环n-1次就足够了,选n-1个最小值。 { int minDis = INF; int cur = 0; for(j=0; j<n; j++) if(!isVisited[j] && dis[j]<minDis) { minDis = dis[j]; cur = j; } if(minDis == INF) //已经完成了连通路径的遍历。 return; //dis[cur]为dis数组中的最小值,访问节点cur. isVisited[cur] = true; //更新Dis数组的内容. for(j=0; j<n; j++) if(road[cur][j] <INF && dis[j] > dis[cur] + road[cur][j]) dis[j] = dis[cur] + road[cur][j]; } } //深度搜索来得到最短路径的数目。 void dfs(int n,int cId,int des,int curDis,int curTeamsNum) { isVisited[cId] = true; if(cId == des) { if(curDis == dis[des]) //找到一条最短路径 { path_num++;//最短路径数目加1 if(curTeamsNum > g_max_team_num) g_max_team_num = curTeamsNum; } return; } if(curDis > dis[des]) //当前的路径长度已经超过最短路径,就没有必要继续搜索了。 return; //从城市cId开始搜索 for(int i=0; i<n; i++) { /* if(!isVisited[i] && road[cId][i] < INF)//如果城市i没有被访问过,且cId到i连通。 { //isVisited[i] = true; dfs(n,i,des,curDis+road[cId][i],curTeamsNum+team_num[i]); isVisited[i] = false; } */ //这样的剪枝比上一种更加强大。 if(dis[cId] + road[cId][i] == dis[i]) dfs(n,i,des,curDis+road[cId][i],curTeamsNum+team_num[i]); } } int main() { int i,j,n,m,c1,c2,L,src,des; initData(); cin>>n>>m>>src>>des; for(i=0; i<n; i++) cin>>team_num[i]; for(i=0; i<m; i++) { cin>>c1>>c2>>L; road[c1][c2] = L; road[c2][c1] = L; } Dijstra(n,src,des); //重置各city的被访问状态。 for(i=0; i<n; i++) isVisited[i] = false; dis[src] = 0; dfs(n,src,des,0,team_num[src]); cout<<path_num<<" "<<g_max_team_num<<endl; return 0; }