题目难以理解,不过最后百度后才理解的大意,其中有一个关键的意思是,如果A到B直接相连,且从A到终点的最短路径大于从B到终点的最短路径,则该人可以从A走向B,问这样走下去,合法路径一共有多少。
直接贴代码,该题让我练习了一下dijkstra和记忆化搜索,说实话,记忆化搜索对于我来说,还真是硬伤。还得没事多练习下。
/*
His office is numbered 1,
and his house is numbered 2.
The first N,
1 < N ≤ 1000, M.
The following
M
1 ≤ d ≤ 1000000
There is at most one path between any pair of intersections.
Output
assume that this number does not exceed 2147483647
Sample Input
5 6
1 3 2
1 4 2
3 4 3
1 5 12
4 2 34
5 2 24
7 8
1 3 1
1 4 1
3 7 1
7 4 1
7 5 1
6 7 1
5 2 1
6 2 1
0
Sample Output
2
4
*/
#include <cstdio>
#include <iostream>
#include <vector>
#include <queue>
#include <utility> //pair头文件
#include <cstring>
#include <string>
using namespace std;
const int V_MAX = 1005;
typedef struct edge
{
int to ,cost;
edge(int a, int b){
to = a;
cost = b;
}
}edge;
unsigned int dp[V_MAX];
int N,M;
vector<edge> G[V_MAX];
typedef pair<int, int > P;
const unsigned int INF = 1<<32 -1;
void cal_minpath(int s)
{
for(int i=1; i<=N; i++)dp[i] = INF;
dp[s] = 0;
priority_queue<P, vector<P >,greater<P > > pque;
pque.push(P(0,s));
while(!pque.empty())
{
P temp = pque.top();
pque.pop();
int len = temp.first;
int V = temp.second;
if(len > dp[V])continue;
for(int i=0;i<G[V].size(); i++)
{
int fir = G[V][i].to;
int sec = G[V][i].cost;
if(dp[fir] > dp[V]+sec)
{
dp[fir] = dp[V] + sec;
pque.push(P(dp[fir], fir));
}
}
}
}
int visited[V_MAX];
unsigned int sum[V_MAX];
unsigned int dfs(int s)
{
if(sum[s]){return sum[s];}
if(s == 2){return 1;}
unsigned int psum = 0;
for(int i=0; i<G[s].size(); i++)
{
edge e = G[s][i];
if(dp[s] > dp[e.to])
{
if(sum[e.to])psum += sum[e.to];
else psum += dfs(e.to);
}
}
sum[s] = psum;
return sum[s];
}
int main(){
while(true)
{
int from,to,cost;
memset(visited,0,sizeof(visited));
memset(sum, 0, sizeof(sum));
memset(G,0,sizeof(G));
scanf("%d", &N);
if(N == 0)break;
scanf("%d", &M);
for(int i=0; i<M; i++)
{
scanf("%d%d%d",&from, &to, &cost);
G[from].push_back(edge(to,cost));
G[to].push_back(edge(from,cost));
}
cal_minpath(2);
cout << dfs(1) << endl;
}
return 0;
}