uva 10917 Walk Through the Forest
gbn最近打算穿过一个森林,但是他比较傲娇,于是他决定只走一些特殊的道路,他打算只沿着满足如下条件的(A,B)道路走:存在一条从B出发回家的路,比所有从A出发回家的路径都短。你的任务是计算一共有多少条不同的回家路径。其中起点的编号为1,终点的编号为2.
Input
多组数据输入,每组数据第一行输入n,m(1<=n<=1000)表示点的数目和边的数目,点的编号为1~n,接下来m行每行输入3个数a,b,c表示有一条双向道路连接a,b长度为c(1<=c<=10^6)当n=0的时候结束输入
Output
对于每组数据输出一个数表示路径的条数,保证答案不超过(2^31)-1。
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
Output for Sample Input
2
4
题目大意:只走(A,B):存在一条从B出发回家的路,比所有从A出发回家的路径都短。问这样的路径有几条。
解题思路:先反向求一遍最短路,得到d数组。当d[B] < d[A]时,满足(A,B)路径,这样就能容易找到(A,B)路径,DFS找一遍总路径数就好了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <queue>
using namespace std;
const int N = 1005;
const int INF = 0x3f3f3f3f;
typedef long long ll;
int n, m, s, t;
int vis[N], d[N];
int map[N][N];
int dp[N];
void init() {
memset(dp, 0, sizeof(dp));
for (int i = 0; i <= n; i++) vis[i] = 0;
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= n; j++) {
if (i == j) map[i][j] = 0;
else map[i][j] = INF;
}
}
}
void input() {
int a, b, c;
for (int i = 0; i < m; i++) {
scanf("%d %d %d", &a, &b, &c);
if (c > map[a][b]) continue;
map[a][b] = map[b][a] = c;
}
}
void SPFA() {
memset(vis,0,sizeof(vis));
for (int i = 0; i < N; i++) d[i] = INF;
d[t] = 0;
vis[t] = 1;
queue<int> Q;
Q.push(t);
while (!Q.empty()) {
int u = Q.front();
Q.pop();
vis[u] = 0;
for (int i = 1; i <= n; i++) {
if (map[u][i] == INF || u == i) continue;
if (d[i] > d[u] + map[u][i]) {
d[i] = d[u] + map[u][i];
if (!vis[i]) {
vis[i] = 1;
Q.push(i);
}
}
}
}
}
int DFS(int pos) {
if (pos == 2) return 1;
if (dp[pos] > 0) {
return dp[pos];
}
int ans = 0;
for (int i = 1; i <= n; i++) {
if (d[pos] > d[i] && map[pos][i] != INF) {
ans += DFS(i);
}
}
return dp[pos] = ans;
}
int main() {
s = 1, t = 2;
while (scanf("%d", &n) != EOF, n) {
init();
scanf("%d", &m);
input();
SPFA();
printf("%d\n", DFS(1));
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不可转载。
时间: 2024-10-09 05:44:57