题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1142
//hdu1142
#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <queue>
#include <vector>
#define INF 0x3f3f3f3f
#define maxn 1005
using namespace std;
vector<int > road[maxn];//存放节点
int map[maxn][maxn], dis[maxn], s[maxn];
//map[i][j]表示i到j的距离, dis[i]为now(当前遍历)节点到i的最短距离
//s[now]为从now节点出发到终点(2节点)有的路的条数
bool vis[maxn];
int n, t, sum;
void init()
{
int i, j;
sum = 0;
memset(s, 0, sizeof(s));
for (i = 0; i <= n; i++)
road[i].clear();
for (i = 0; i <= n; i++)
for (j = 0; j <= n; j++) {
if (i == j)
map[i][j] = 0;
else
map[i][j] = INF;
}
}
void input()
{
int a, b, d;
while (t--)
{
scanf("%d%d%d", &a, &b, &d);
if (d < map[a][b]) {
map[a][b] = map[b][a] = d;
road[a].push_back(b);
road[b].push_back(a);
}
}
}
void SPFA()
{
int i, now;
memset(vis, false, sizeof(vis));
for (i = 1; i <= n; i++)
dis[i] = INF;
dis[2] = 0;
queue<int >q;
q.push(2);
vis[2] = true;
while (!q.empty())
{
now = q.front();
q.pop();
vis[now] = false;
for (i = 1; i <= n; i++) {//更新now到i的最短距离为dis[i]
if (dis[i] > dis[now] + map[now][i]) {
dis[i] = dis[now] + map[now][i];
if (vis[i] == false) {//i节点入栈,标记i节点为已访问
q.push(i);
vis[i] = true;
}
}
}
}
}
int dfs(int now)//记忆化搜索
{
int i;
if (now == 2) return 1;//找到终点返回1
if (s[now]) return s[now];//如果有路经过now点,返回过该点路的数量
for (i = 0; i < road[now].size(); i++) {
if (dis[now] > dis[road[now][i]])//更新到now节点路的数量
s[now] += dfs(road[now][i]);
}
return s[now];
}
int main()
{
while (scanf("%d", &n), n)
{
scanf("%d", &t);
init();
input();
SPFA();
sum = dfs(1);
printf("%d\n", sum);
}
return 0;
}