思路:①我们把每条边的信息放到node中,然后添边和更新
②当找到比当前最短路还小的权值时,要更新次短路和最短路,在这里要判断一下,当前最短路是不是在之前已经出现过,如果没有出现则不更新次短路只更新最短路。否则两个都更新
③如果当前找到的最短路和已经查找到的最短路相同时,这是只要记录最短路的条数就可以
④如果当前找到的值在最短路和次短路之间,那么只需要更新次短路
⑤如果当前找的值和次短路相同那么次短路的条数更新
#include<iostream> #include<cstdio> #include<algorithm> #include<string.h> #include<queue> #include<vector> #define inf 1<<30 using namespace std; const int maxn=55; struct Edge { int to; int w; }; struct node { int v,dist,mark; bool friend operator <(const node &a,const node &b) { if(a.dist!=b.dist) return a.dist>b.dist; return a.v>b.v; } }; int dis[maxn][3]; int dp[maxn][3]; int vis[maxn][3]; priority_queue<node>Q; vector<Edge>gra[maxn]; int N,M,S,E; void init() { for(int i=0;i<maxn;i++) { dis[i][1]=dis[i][2]=inf; // dp[i][1]=dp[i][2]=0; // vis[i][1]=vis[i][2]=0; } //用for()循环 15毫秒 //memset() 0毫秒 memset(dp,0,sizeof(dp)); memset(vis,0,sizeof(vis)); } void Dijstra(int s,int e) { node p,q,tem; dp[s][1]=1; dis[s][1]=0; q.dist=0; q.mark=1; q.v=s; Q.push(q); while(!Q.empty()) { p=Q.top(); Q.pop(); if(vis[p.v][p.mark])//判断一个点是不是 被访问过 continue; vis[p.v][p.mark]=1; for(int i=0;i<gra[p.v].size();i++) { int vv=gra[p.v][i].to; int ww=gra[p.v][i].w; if(!vis[vv][1]&&dis[vv][1]>p.dist+ww)//如果可以判断为最短路 { if(dis[vv][1]!=inf)//如果在之前的状态中已经找到了一条最短路 { dis[vv][2]=dis[vv][1]; dp[vv][2]=dp[vv][1]; q.mark=2; q.dist=dis[vv][2]; q.v=vv; Q.push(q); } dis[vv][1]=p.dist+ww; dp[vv][1]=dp[p.v][p.mark]; q.mark=1; q.dist=dis[vv][1]; q.v=vv; Q.push(q); } else if(!vis[vv][1]&&dis[vv][1]==p.dist+ww) { dp[vv][1]+=dp[p.v][p.mark]; } else if(!vis[vv][2]&&dis[vv][2]>p.dist+ww) { dis[vv][2]=p.dist+ww; dp[vv][2]=dp[p.v][p.mark]; q.mark=2; q.dist=dis[vv][2]; q.v=vv; Q.push(q); } else if(!vis[vv][2]&&dis[vv][2]==p.dist+ww) { dp[vv][2]+=dp[p.v][p.mark]; } } } } int main() { int n1,n2,n3; Edge tem; while(scanf("%d%d%d%d",&N,&M,&S,&E)!=EOF) { for(int i=0;i<maxn;i++) gra[i].clear(); init(); for(int i=0;i<M;i++) { scanf("%d%d%d",&n1,&n2,&n3); tem.to=n2; tem.w=n3; gra[n1].push_back(tem); } Dijstra(S,E); printf("%d %d\n",dis[E][2],dp[E][2]); } return 0; }