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
", 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("
");
 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
", 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
", 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 ", dist[en] == INF ? -1 : dist[en]);

     

原文地址:https://www.cnblogs.com/windysai/p/3730923.html