hdu 2544 最短路 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544
题目意思:给出 n 个路口和 m 条路,每一条路需要 c 分钟走过。问从路口 1 到路口 n 需要的最短时间是多少。
这题是最短路的入门题,从理解d-i--j---k(wg自创的,呵呵)到默打到修改,搞左两日终于好了,哈哈哈~~~太感动了。
第一次错是 少了Dijkstra()函数中的 for (j = 1; j <= n; j++) 。
第二次错是把vis[k=j]=1 写在了 if (!vis[j] && dist[j] < mini) 里面。
好好总结自己的错误,以后应该能避免了。(做完郑多燕后,灵感翻来了,成日系实验室里对住堆恶心的实验报告兼做5成功,有种令人想死的感觉,忽略忽略)
顺便帮大家普及下科学知识,经过我的搜罗,
dijkstra /ˈdɛɪkstra/
别读成 d - i - j -k 了
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespace std; 6 7 #define INF 100000000 8 const int maxn = 100 + 10; 9 int dist[maxn], map[maxn][maxn], vis[maxn]; 10 int n, m; 11 12 void Init() 13 { 14 int i, j, st, en, cost; 15 for (i = 1; i <= n; i++) 16 dist[i] = (i == 1 ? 0 : INF); 17 memset(vis, 0, sizeof(vis)); 18 for (i = 1; i <= n; i++) 19 { 20 for (j = 1; j <= n; j++) 21 map[i][j] = INF; // 这样也行:map[i][j] = map[j][i] = (i == j ? 0 : INF); 22 } 23 for (i = 1; i <= m; i++) 24 { 25 scanf("%d%d%d", &st, &en, &cost); 26 map[st][en] = map[en][st] = cost; // 建立邻接矩阵 27 } 28 } 29 30 void Dijkstra() 31 { 32 int i, j, k, mini; 33 for (i = 1; i <= n; i++) 34 { 35 mini = INF; 36 for (j = 1; j <= n; j++) // 这个循环是用来找出与第i个点最近的点(当然是直接有边相连) 37 { 38 if (!vis[j] && dist[j] < mini) 39 { 40 mini = dist[j]; 41 k = j; 42 } 43 } 44 vis[k] = 1; // 如果把这句放在上面的if里面,就会把有些不该被标记已经过的点置1了,实质只需要置距离i点最短的那个点 45 for (j = 1; j <= n; j++) 46 { 47 if (dist[j] > mini + map[k][j]) // mini其实就是dist[k],mini + map[k][j]表示绕过k点走到j点的路径会不会比直接不绕过k要短 48 dist[j] = mini + map[k][j]; // dist[j] = dist[k]+ map[k][j; 49 } 50 } 51 } 52 53 int main() 54 { 55 while(scanf("%d%d", &n, &m) && (m || n)) 56 { 57 Init(); 58 Dijkstra(); 59 printf("%d\n", dist[n]); 60 } 61 return 0; 62 }
邻接表 + 优先队列 + dijkstra (好强大,^_^)
http://mindlee.net/2011/11/18/shortest-paths-algorithm/
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <climits> // 定义各种数据类型最值得常量,如下面的INF_MAX: 2147483647 5 #include <queue> 6 using namespace std; 7 8 const int NV = 100 + 5; 9 const int NE = 2e4 + 5; 10 11 int n, m; 12 13 struct Dijkstra 14 { 15 int n, size; 16 int dis[NV], head[NV]; 17 int mark[NV]; 18 19 struct node 20 { 21 int v, dis; 22 node() {} 23 node(int V, int DIS): v(V), dis(DIS){} 24 friend bool operator < (const node a, const node b) 25 { 26 return a.dis > b.dis; // 结构体中,dis小的优先级高 27 } 28 }; 29 30 struct edge 31 { 32 int v, w, next; 33 edge() {} 34 edge(int V, int W, int NEXT): v(V), w(W), next(NEXT) {} 35 }E[NE]; 36 37 inline void init(int vx) 38 { 39 n = vx, size = 0; 40 memset(head, -1, sizeof(int)*(vx+1)); 41 } 42 43 inline void insert(int u, int v, int w) 44 { 45 E[size] = edge(v, w, head[u]); // E[size]. v = u, E[size].w = v, E[size].next = head[u] 46 head[u] = size++; 47 } 48 49 /* void print() // 打印每个点的邻接表 50 { 51 for (int i = 0; i < n; i++) 52 { 53 printf("%d: ", i); 54 for (int j = head[i]; j != -1; j = E[j].next) 55 { 56 printf(" %d", E[j].v); 57 } 58 printf("\n"); 59 } 60 } 61 */ 62 int dijkstra(int src, int des) // src: 0 des: n-1 63 { 64 node first, next; 65 priority_queue<node> Q; 66 for (int i = 0; i <= n; i++) 67 { 68 dis[i] = INT_MAX; 69 mark[i] = false; 70 } 71 dis[src] = 0; 72 Q.push(node(src, 0)); // 把起始点入队 73 74 while (!Q.empty()) 75 { 76 first = Q.top(); 77 Q.pop(); 78 mark[first.v] = true; 79 80 for (int i = head[first.v]; i != -1; i = E[i].next) 81 { 82 if (!mark[E[i].v]) 83 { 84 next = node(E[i].v, first.dis + E[i].w); 85 if (next.dis < dis[next.v]) 86 { 87 dis[next.v] = next.dis; 88 Q.push(next); 89 } 90 } 91 } // end for 92 } // end while 93 return dis[des]; 94 } // end dijkstra 95 }G; 96 97 int main() 98 { 99 while (scanf("%d%d", &n, &m) != EOF && (m + n)) 100 { 101 G.init(n); 102 while (m--) 103 { 104 int u, v, w; 105 scanf("%d%d%d", &u, &v, &w); 106 G.insert(u-1, v-1, w); 107 G.insert(v-1, u-1, w); 108 } 109 // G.print(); 110 printf("%d\n", G.dijkstra(0, n-1)); 111 } 112 return 0; 113 }
Spfa + 邻接矩阵
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 using namespace std; 6 7 const int INF = 1e9; 8 const int maxn = 100 + 5; 9 int dist[maxn], map[maxn][maxn]; 10 bool mark[maxn]; 11 int N, M; 12 13 int Spfa() 14 { 15 for (int i = 1; i <= N; i++) 16 { 17 mark[i] = false; 18 dist[i] = INF; 19 } 20 queue<int> Q; 21 dist[1] = 0; 22 mark[1] = true; 23 Q.push(1); 24 25 while (!Q.empty()) 26 { 27 int first = Q.front(); 28 Q.pop(); 29 mark[first] = false; 30 31 for (int i = 1; i <= N; i++) 32 { 33 if (dist[first] + map[first][i] < dist[i]) 34 { 35 if (!mark[i]) 36 { 37 Q.push(i); 38 mark[i] = true; // mark 写在dist[i] 下一行也能过 39 } 40 dist[i] = dist[first] + map[first][i]; 41 // mark[i] = true; 42 } 43 } 44 } 45 return dist[N]; 46 } 47 48 int main() 49 { 50 while (scanf("%d%d", &N, &M) != EOF && (N+M)) 51 { 52 int A, B, C; 53 for (int i = 1; i <= N; i++) 54 { 55 map[i][i] = INF; 56 for (int j = i+1; j <= N; j++) 57 map[i][j] = map[j][i] = INF; // 双向边!!! 58 } 59 while (M--) 60 { 61 scanf("%d%d%d", &A, &B, &C); 62 map[A][B] = map[B][A] = C; 63 } 64 printf("%d\n", Spfa()); 65 } 66 return 0; 67 }
顺便写写:1874
scanf("%d%d", &st, &en); // st:起点 en:终点
for (int i = 0; i < n; i++)
{
dist[i] = map[st][i]; // 构建起点到其他点之间的距离,INF代表不可达
}
输出注意下即可:printf("%d\n", dist[en] == INF ? -1 : dist[en]);