题意:从2到1的所有路径中找出最短的路,并且输出最短路径有几条。
策略:先求出最短路径,然后再找出从2到1的最短路径有几条。最短路径用dijkstra算法来求出,什么是dijkstra算法,简单来说,dijkstra算法就是路径长度递增次序产生最短路径的算法:
基本思想是:把集合V分成两组;
(1)S:已求出最短路径的顶点的集合
(2)V-S=T:尚未确定最短路径的顶点集合
将T中顶点按最短路径递增的次序加入到S中,
保证:(1)从源点V0到S中各顶点的最短路径长度都不大于
从V0到T中任何顶点的最短路径长度
(2)每个顶点对应一个距离值
S中顶点:从V0到此顶点的最短路径长度
T中顶点:从V0到此顶点的只包括S中顶点作中间
顶点的最短路径长度
话不多说,思想是基础,最重要的还是怎么样实现:我们就以这道题为例子:
代码:
#include<stdio.h> #include<string.h> #define INF 0x3f3f3f3f//不能换成0x7fffffff, 因为下面有个di[min_pos]+INF, 结果是会超INT范围的 #define MAXN 1007 int map[MAXN][MAXN], di[MAXN], ans[MAXN]; //map是邻接矩阵, di是存储的源点到各点的最小距离 bool vis[MAXN];//标记 int n; void dijkstra(int v) { int i, j; memset(vis, 0, sizeof(vis)); //初始化 di[v] = 0; vis[v] = 1; for(i = 1; i <= n; i ++){ if(!vis[i]){ di[i] = map[v][i]; } } for( i = 1; i < n; i ++){ int min = INF; int min_pos = 0;//这个一定要等于0,不然的话会RE for(j = 1; j <= n; j ++){ if(!vis[j]&&di[j] < min){ min = di[j]; min_pos = j; } } vis[min_pos] = 1; for(j = 1; j <= n; j ++){ if(!vis[j]&&di[j] > map[min_pos][j]+di[min_pos]){ di[j] = map[min_pos][j]+di[min_pos]; } } } } int dfs(int v) //深搜:原理:从1点出发,每次一都找比当前di[v]小的点,找到二就说明有一条最短路径 { if(ans[v] != -1) return ans[v]; //记忆化搜索 if(v == 2) return 1;//找到2就说名有一条路 ans[v] = 0; //初始化 for(int i = 1; i <= n; i ++){ if(map[v][i]!= INF&&di[i] < di[v]){ //map[v][i]!= INF 是为了判断v与i是不是有路 ans[v] += dfs(i); } } return ans[v]; } int main() { int m, i, j, a, b, c; while(scanf("%d", &n), n){ scanf("%d", &m); for(i = 1; i <= n; i ++){//初始化,map[i][i] = 0;map[i][j] = INF; for(j = 1; j <= n; j ++){ map[i][j] = i==j?0:INF; } } for(i = 0; i < m; i ++){ scanf("%d%d%d", &a, &b, &c); map[a][b] = map[b][a] = c; } dijkstra(2); //for(i = 1; i <= n; i ++){ // printf("%d..%d\n", di[i], i); //} memset(ans, -1, sizeof(ans)); printf("%d\n", dfs(1)); } return 0; }
HDOJ 1142 A Walk Through the Forest 【Dijkstra】+【DFS】
时间: 2024-10-12 19:15:32