思路:①我们把每条边的信息放到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;
}