hdu_A Walk Through the Forest ——迪杰特斯拉+dfs

A Walk Through the Forest

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 3   Accepted Submission(s) : 1

Problem Description

Jimmy experiences a lot of stress at work these days, especially since his accident made working difficult. To relax after a hard day, he likes to walk home. To make things even nicer, his office is on one side of a forest, and his house is on the other. A nice walk through the forest, seeing the birds and chipmunks is quite enjoyable.
The forest is beautiful, and
Jimmy wants to take a different route everyday. He also wants to get home before
dark, so he always takes a path to make progress towards his house. He considers
taking a path from A to B to be progress if there exists a route from B to his
home that is shorter than any possible route from A. Calculate how many
different routes through the forest Jimmy might take.

Input

Input contains several test cases followed by a line
containing 0. Jimmy has numbered each intersection or joining of paths starting
with 1. His office is numbered 1, and his house is numbered 2. The first line of
each test case gives the number of intersections N, 1 < N ≤ 1000, and the
number of paths M. The following M lines each contain a pair of intersections a
b and an integer distance 1 ≤ d ≤ 1000000 indicating a path of length d between
intersection a and a different intersection b. Jimmy may walk a path any
direction he chooses. There is at most one path between any pair of
intersections.

Output

For each test case, output a single integer indicating
the number of different routes through the forest. You may 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

Source

University of Waterloo Local Contest 2005.09.24

题意:Jimmy工作压力大,为了放松,他喜欢走路回家。而为了不太晚到家,他又得朝着家的方向走,也就是说必须离家越来越近。给定一个无向图,求有多少条路径回家。

分析:先用迪杰特斯拉算法求出各结点离源点(家)的最短距离,然后dfs求出路径总数。

时间超限代码(dfs需优化)

 1 #include <cstdio>
 2 #include <queue>
 3 #include <algorithm>
 4 #define INF 0x3f3f3f3f
 5 using namespace std;
 6
 7 const int maxn=1001;
 8 vector<int> g[maxn];
 9 struct node
10 {
11     int num,dis;
12 };
13 int n,m;
14 int cost[maxn][maxn],d[maxn];
15 int ans;
16
17 bool operator<(const node& n1,const node& n2)
18 {
19     return n1.dis<n2.dis;
20 }
21
22 void dij()
23 {
24     fill(d+1,d+n+1,INF);
25     d[2]=0;
26     priority_queue<node> que;
27     que.push(node{2,0});
28     while(!que.empty())
29     {
30         int x=que.top().num;
31         que.pop();
32         for(int i=0;i<g[x].size();i++)
33         {
34             int u=x;
35             int v=g[x][i];
36             if(d[v]>d[u]+cost[u][v])
37             {
38                 d[v]=d[u]+cost[u][v];
39                 que.push(node{v,d[v]});
40             }
41         }
42     }
43 }
44
45 void dfs(int x)
46 {
47     if(x==2)
48     {
49         ans++;
50         return ;
51     }
52     for(int i=0;i<g[x].size();i++)
53     {
54         int fx=g[x][i];
55         if(d[fx]<d[x])
56            dfs(fx);
57     }
58 }
59
60 int main()
61 {
62     while(scanf("%d",&n),n)
63     {
64         scanf("%d",&m);
65         ans=0;
66         for(int i=1;i<=n;i++)
67             for(int j=1;j<=n;j++)
68         {
69             cost[i][j]=(i==j)?0:INF;
70         }
71         for(int i=0;i<m;i++)
72         {
73             int a,b,c;
74             scanf("%d%d%d",&a,&b,&c);
75             g[a].push_back(b);
76             g[b].push_back(a);
77             cost[a][b]=cost[b][a]=c;
78         }
79         dij();
80         d[2]=0;
81         dfs(1);
82         printf("%d\n",ans);
83         for(int i=1;i<=n;i++)
84             g[i].clear();
85         ans=0;
86     }
87     return 0;
88 }

优化分析:存在对某些结点进行了多次dfs,导致时间耗费过多。考虑采用记忆化搜索。我们用sum[i]表示从i出发有多少条到家的路径,对于已知sum[i]的结点i就不需要再次dfs,这样dfs的次数就只有n-1次(n为结点数)。

优化后代码:用时514ms

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 #include <algorithm>
 5 #define INF 0x3f3f3f3f
 6 using namespace std;
 7
 8 const int maxn=1001;
 9 vector<int> g[maxn];//图的邻接表表示
10 struct node
11 {
12     int num,dis;
13 };
14 int n,m;
15 int cost[maxn][maxn],d[maxn];
16 int sum[maxn];
17
18 bool operator<(const node& n1,const node& n2)//重载运算符
19 {
20     return n1.dis<n2.dis;
21 }
22
23 void dij()
24 {
25     fill(d+1,d+n+1,INF);//下标从1开始
26     d[2]=0;
27     priority_queue<node> que;
28     que.push(node{2,0});
29     while(!que.empty())
30     {
31         int x=que.top().num;
32         que.pop();
33         for(int i=0;i<g[x].size();i++)
34         {
35             int u=x;
36             int v=g[x][i];
37             if(d[v]>d[u]+cost[u][v])
38             {
39                 d[v]=d[u]+cost[u][v];
40                 que.push(node{v,d[v]});
41             }
42         }
43     }
44 }
45
46 void dfs(int x)
47 {
48     for(int i=0;i<g[x].size();i++)
49     {
50         int fx=g[x][i];
51         if(d[fx]<d[x])
52         {
53             if(sum[fx]>0)
54             {
55                 sum[x]+=sum[fx];
56             }
57             else
58             {
59
60
61             dfs(fx);
62             sum[x]+=sum[fx];
63             }
64         }
65     }
66   //  return ;
67 }
68
69 int main()
70 {
71     while(scanf("%d",&n),n)
72     {
73         scanf("%d",&m);
74         memset(sum,0,sizeof(sum));
75         for(int i=1;i<=n;i++)
76             for(int j=1;j<=n;j++)
77         {
78             cost[i][j]=(i==j)?0:INF;
79         }
80         for(int i=0;i<m;i++)
81         {
82             int a,b,c;
83             scanf("%d%d%d",&a,&b,&c);
84             g[a].push_back(b);
85             g[b].push_back(a);
86             cost[a][b]=cost[b][a]=c;
87         }
88         dij();
89         sum[2]=1;
90         dfs(1);
91         printf("%d\n",sum[1]);
92         for(int i=1;i<=n;i++)
93             g[i].clear();
94     }
95     return 0;
96 }

此题bug过的地方

(1)fill(d+1,d+1+n,INF),一开始没注意下标是从1开始,写成了fill(d,d+n,INF)。dij函数bug。

(2)每组用例输出后没有清空图,导致下一组用例的图多了许多不属于自己的边和顶点。

时间: 2024-08-01 21:03:21

hdu_A Walk Through the Forest ——迪杰特斯拉+dfs的相关文章

51nod 1459迷宫游戏,迪杰特斯拉算法

1459 迷宫游戏 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 你来到一个迷宫前.该迷宫由若干个房间组成,每个房间都有一个得分,第一次进入这个房间,你就可以得到这个分数.还有若干双向道路连结这些房间,你沿着这些道路从一个房间走到另外一个房间需要一些时间.游戏规定了你的起点和终点房间,你首要目标是从起点尽快到达终点,在满足首要目标的前提下,使得你的得分总和尽可能大.现在问题来了,给定房间.道路.分数.起点和终点等全部信息,你能计算在尽快离开迷宫的前提下,你的最大得

最短路径---Dijkstra迪杰特斯拉算法---《数据结构》严蔚敏

// exam1.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #include <stack> using namespace std; #define MAXVEX 20 #define INT_MAX 10000 typedef struct ArcNode { int adj; void* info; }ArcNode; typedef ArcNode AdjMat[MAX

HDU 1142 A Walk Through the Forest(dijkstra+记忆化DFS)

题意: 给你一个图,找最短路.但是有个非一般的的条件:如果a,b之间有路,且你选择要走这条路,那么必须保证a到终点的所有路都小于b到终点的一条路.问满足这样的路径条数 有多少,噶呜~~题意是搜了解题报告才明白的Orz....英语渣~ 思路: 1.1为起点,2为终点,因为要走ab路时,必须保证那个条件,所以从终点开始使用单源最短路Dijkstra算法,得到每个点到终点的最短路,保存在dis[]数组中. 2.然后从起点开始深搜每条路,看看满足题意的路径有多少条. 3.这样搜索之后,dp[1]就是从起

1111 Online Map(迪杰斯特拉+DFS)

题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805358663417856 输出要求: 翻译结果: 在最短路径不唯一的情况下,输出最短路径中最快的一条,保证唯一. 如果最快的路径不是唯一的,则输出通过最少交叉口的路径,该交叉口保证是唯一的.如果最短路径和最快路径相同,请按以下格式将它们打印在一行中: 题目思路很简答,使用两个不同度量(距离.时间)的 迪杰斯特拉+DFS 求解即可. PS:我英语好菜,我翻译错了,

43. 蛤蟆的数据结构笔记之四十三最短路径之迪杰斯特拉(Dijkstra )算法

43. 蛤蟆的数据结构笔记之四十三最短路径之迪杰斯特拉(Dijkstra )算法 本篇名言:"辛勤的蜜蜂永没有时间悲哀.--布莱克" 这次来看下Dijkstra )算法.还是老方法,先原理,后实现.代码来自网络. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47046031 1.  最短路径 最短路径问题是图论研究中的一个经典算法问题, 旨在寻找图(由结点和路径组成的)中两结点之间的最短路径. 管道铺设.线路安排

hdu 1142(迪杰斯特拉+记忆化搜索)

A Walk Through the Forest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7330    Accepted Submission(s): 2687 Problem Description Jimmy experiences a lot of stress at work these days, especiall

HDU1142 A Walk Through the Forest(dijkstra)

A Walk Through the Forest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7733    Accepted Submission(s): 2851 Problem Description Jimmy experiences a lot of stress at work these days, especiall

POJ 2502 Subway(迪杰斯特拉)

Subway Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6692   Accepted: 2177 Description You have just moved from a quiet Waterloo neighbourhood to a big, noisy city. Instead of getting to ride your bike to school every day, you now get

最短路径算法——迪杰斯特拉算法(Dijkstra)

图结构中应用的最多的就是最短路径的查找了,关于最短路径查找的算法主要有两种:迪杰斯特拉算法(Dijkstra)和Floyd算法. 其中迪杰斯特拉算法(Dijkstra)实现如下: 原理就是不断寻找当前的最优解: void main() { int V[Max][Max]={0,8,32,Infinity,Infinity, 12,0,16,15,Infinity, Infinity,29,0,Infinity,13, Infinity,21,Infinity,0,7, Infinity,Infi