首先来弄清楚题意:如果从A、B两点相连接,并且B点到终点距离小于A点到终点的距离,那么就走A->B这段路,问你最后有多少种不同的路线到达终点。
根据题意能够知道,只有离终点越近的路段才能走,例如第一个样例里面,1->4可以走,但是1->3不可以走,因为1到终点距离是36,要小于3到终点的距离37。
那么我们可以先从终点跑一遍最短路,然后再从起点开始选择路径,看按照每走一段路就离终点越近的规则,能有多少条路到达终点。
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <iomanip>
#include <string>
using namespace std;
const int maxn=1e3+5;
const int INF=0x3f3f3f3f;
int n,m,a,b,val;
struct P{
int to,cost;
bool operator<(const P&a)const{
return cost>a.cost;
}
};
vector<P> edge[maxn];
int dis[maxn],vis[maxn],sum[maxn];
void ini(){
for(int i=0;i<maxn;i++) edge[i].clear();
memset(vis,0,sizeof(vis));
memset(dis,INF,sizeof(dis));
memset(sum,0,sizeof(sum));
}
void SPFA(){
priority_queue<P> qu;
qu.push(P{2,0});
dis[2]=0;
while(!qu.empty()){
P now=qu.top();
qu.pop();
if(vis[now.to]) continue;
vis[now.to]=1;
for(int i=0;i<edge[now.to].size();i++){
P nxt=edge[now.to][i];
if(dis[nxt.to]>=dis[now.to]+nxt.cost){
dis[nxt.to]=dis[now.to]+nxt.cost;
qu.push(P{nxt.to,dis[nxt.to]});
}
}
}
}
int DFS(int now){
if(now==2) return 1;//到达终点表明有一条路满足
if(sum[now]) return sum[now];//记忆化搜索剪枝
for(int i=0;i<edge[now].size();i++)
if(dis[now]>dis[edge[now][i].to])//谁更近就朝谁走
sum[now]+=DFS(edge[now][i].to);//当前节点的选择等于所有子节点的选择
return sum[now];
}
int main()
{
while(scanf("%d",&n) && n){
scanf("%d",&m);
ini();
for(int i=1;i<=m;i++){
scanf("%d%d%d",&a,&b,&val);
edge[a].push_back(P{b,val});
edge[b].push_back(P{a,val});
}
SPFA();//其实是Dijkstra
int ans=DFS(1);
printf("%d\n",ans);
}
return 0;
}