ACM/ICPC 之 两道dijkstra练习题(ZOJ1053(POJ1122)-ZOJ1053)

  两道较为典型的单源最短路径问题,采用dijkstra解法

  本来是四道练习题,后来发现后面两道用dijkstra来解的话总觉得有点冗余了,因此暂且分成三篇博客(本篇以及后两篇)。

 

 

 

ZOJ1053(POJ1122)-FDNY to the Rescue!

 

 1 //POJ1122-ZOJ1053
 2 //dijkstra-需要记录路径
 3 //给出n个路口的邻接矩阵,求给定多个火警到失火点的时间及任一路径
 4 //注意输入最后一行时,cin.getline需要两次,猜测需要接受邻接矩阵最后一行其他字符后再接受下一行(有误请指出)
 5 //POJ1122:Time:16Ms    Memory:208K    (单组数据)
 6 //ZOJ1053:Time:0Ms    Memory:276K    (多组数据,中间空一行)
 7 #include<iostream>
 8 #include<cstring>
 9 #include<cstdio>
10 #include<algorithm>
11 using namespace std;
12 
13 #define MAX 21
14 #define INF 0x3f3f3f3f
15 
16 struct FD {    //FDNY
17     int d;    //到失火点的距离
18     int num;    //FD编号
19     friend bool operator < (FD fd1, FD fd2) { return fd1.d < fd2.d; }
20 }fd[MAX];
21 
22 int n;
23 int road[MAX][MAX];    //有向图-road[i][j]:从i到j的距离
24 int d[MAX];
25 int fa[MAX];
26 bool v[MAX];
27 
28 void dijkstra(int x)
29 {
30     memset(v, false, sizeof(v));
31     v[x] = true;
32     for (int i = 1; i <= n; i++)
33     {
34         d[i] = road[i][x];
35         fa[i] = x;
36     }
37     for (int i = 1; i <= n; i++)
38     {
39         int mind = INF;
40         int k;
41         for (int j = 1; j <= n; j++)
42             if (!v[j] && mind > d[j])
43             {
44                 mind = d[j];
45                 k = j;
46             }
47         if (mind == INF) return;
48         v[k] = true;
49         for (int j = 1; j <= n; j++)
50             if (!v[j] && d[j] > d[k] + road[j][k])
51             {
52                 d[j] = d[k] + road[j][k];
53                 fa[j] = k;
54             }
55     }
56 }
57 
58 int main()
59 {
60     int T;
61     scanf("%d", &T);
62     char str[2*MAX];
63     cin.getline(str,2*MAX);
64     while (T--)
65     {
66         scanf("%d", &n);
67         for (int i = 1; i <= n; i++)
68             for (int j = 1; j <= n; j++)
69             {
70                 scanf("%d", &road[i][j]);
71                 if (road[i][j] == -1) road[i][j] = INF;
72             }
73         cin.getline(str, 2 * MAX);
74         cin.getline(str, 2 * MAX);
75 
76         dijkstra(str[0] - '0');
77         printf("Org\tDest\tTime\tPath\n");
78         int lenfd = 0;
79         int len = strlen(str);
80         for (int i = 2; i < len; i += 2)
81         {
82             fd[lenfd].num = str[i] - '0';
83             fd[lenfd++].d = d[str[i] - '0'];
84         }
85 
86         sort(fd, fd + lenfd);
87         for (int i = 0; i < lenfd; i++)
88         {
89             printf("%d\t%d\t%d\t%d", fd[i].num, str[0] - '0', fd[i].d, fd[i].num);
90             int x = fd[i].num;
91             while (fa[x] != x)
92                 printf("\t%d", x = fa[x]);
93             printf("\n");
94         }
95         if(T) printf("\n");
96     }
97     return 0;
98 }

 

 

 

 

ZOJ1053-Transport Goods

 

 1 //dijkstra-松弛变形
 2 //题意中的cost请理解为Goods的代价(即消耗Goods的比例),可以比作路上会因各种情况损失货物的比例
 3 //博主用的是普通的最短路,不过WA了好几发,初始化-去重-松弛处理都有过问题(做了几个小时啊...)
 4 //可以转化为最长路,精度比博主会更好,不过针对此题并无必要
 5 //Time:0Ms    Memory:360K
 6 #include<iostream>
 7 #include<cstring>
 8 #include<cstdio>
 9 using namespace std;
10 
11 #define MAX 105
12 #define INF 0x7f7f7f7f
13 
14 int n, m;
15 double cost[MAX][MAX];
16 double d[MAX], w[MAX];
17 bool v[MAX];
18 
19 void dijkstra()
20 {
21     memset(v, false, sizeof(v));
22     v[n] = true;
23     for (int i = 1; i < n; i++)
24         d[i] = cost[i][n];
25     for (int i = 1; i <= n; i++)
26     {
27         double mind = 1;    //以1为上界
28         int k;
29         for (int j = 1; j < n; j++)
30         {
31             if (!v[j] && mind > d[j])
32             {
33                 mind = d[j];
34                 k = j;
35             }
36         }
37         if (mind > 1)    return;
38         v[k] = true;
39         for (int j = 1; j < n; j++)    //松弛
40             if (!v[j] && cost[k][j] < 1 && d[j] > 1 - (1 - d[k]) * (1 - cost[k][j]))
41                 d[j] = 1 - (1 - d[k]) * (1 - cost[k][j]);
42     }
43 }
44 
45 int main()
46 {
47     //freopen("in.txt", "r", stdin);
48     //freopen("out.txt", "w", stdout);
49     while (scanf("%d%d", &n, &m) != EOF)
50     {
51         memset(cost, INF, sizeof(cost));
52         memset(w, 0, sizeof(w));
53         for (int i = 1; i < n; i++)
54             scanf("%lf", &w[i]);
55         for (int j = 0; j < m; j++)
56         {
57             int x, y;
58             double r;
59             scanf("%d%d%lf", &x, &y, &r);
60             if (cost[x][y] > r)        //去重
61                 cost[y][x] = cost[x][y] = r;
62         }
63         dijkstra();
64         for (int i = 1; i < n; i++)
65             if (d[i] < 1)
66                 w[n] += (1 - d[i]) * w[i];
67         printf("%.2f\n", w[n]);
68     }
69     return 0;
70 }

 

    原文作者:算法小白
    原文地址: https://www.cnblogs.com/Inkblots/p/5452414.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞