Hdu 5361 In Touch (dijkatrs+优先队列)

题目链接:

  Hdu 5361  In Touch

题目描述:

  有n个传送机排成一排,编号从1到n,每个传送机都可以把自己位置的东西传送到距离自己[l, r]距离的位置,并且花费c,问从1号传送机到其他传送机的最小花费是多少??

解题思路:

  看了题解发现是dijkstra(求最短单源路径)+并查集(优化),刚开始的时候并不知道怎么用并查集优化,然后就提交了一个没有并查集的代码,果断TLE。然后开始搜代码,突然惊叹真是优化的太美妙。因为每次从队列中取出的都是最优的,所以更新dis的时候可以直接把这些点合并,下次再遇到这些点的时候没必要更新就直接跳过。(在这里要特别谢谢为我debug快要疯了的天I火聚聚)

 1 #include <cmath>
 2 #include <queue>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <iostream>
 6 #include <algorithm>
 7 using namespace std;
 8 typedef long long LL;
 9 const LL INF = 1LL<<62;
10 const int maxn = 200005;
11 struct node
12 {
13     int x;
14     LL dis;
15     node (int a, LL b):x(a),dis(b){}
16     friend bool operator < (node a, node b)
17     {
18         return a.dis > b.dis;
19     }
20 };
21 int l[maxn], r[maxn], c[maxn], father[maxn], n;
22 LL dis[maxn];
23 int Find (int x)
24 {
25     if (x != father[x])
26         father[x] = Find (father[x]);
27         return father[x];
28 }
29 void Merge (int x, int y)
30 {
31     int px = Find(x);
32     int py = Find(y);
33     if (px == py)
34         return ;
35     father[px] = py;
36 }
37 void dijkstra (int x)
38 {
39     priority_queue <node> Q;
40     dis[x] = c[x];
41     Q.push(node(x, dis[x]));
42     while (!Q.empty())
43     {
44         int p = Q.top().x;
45         Q.pop();
46         for (int i=-1; i<=1; i+=2)
47         {
48             int L = p + l[p]*i;
49             int R = p + r[p]*i;
50             if (L > R)
51                 swap(L, R);
52             L = max (L, 1);
53             R = min (R, n);
54             for (int j=L; j<=R; j++)
55             {
56                 j = Find (j);
57                 if ( j > R)
58                     break;
59                 if (dis[j] > dis[p] + c[j])
60                 {
61                     dis[j] = dis[p] + c[j];
62                     Q.push(node(j, dis[j]));
63                 }
64                 Merge (j, j+1);
65             }
66         }
67     }
68 }
69 int main ()
70 {
71     int t;
72     scanf ("%d", &t);
73     while (t --)
74     {
75         scanf ("%d", &n);
76         for (int i=1; i<=n; i++)
77             scanf ("%d", &l[i]);
78         for (int i=1; i<=n; i++)
79             scanf ("%d", &r[i]);
80         for (int i=1; i<=n; i++)
81             scanf ("%d", &c[i]);
82         for (int i=0; i<=n+1; i++)
83             {
84                 father[i] = i;
85                 dis[i] = INF;
86             }
87             dijkstra (1);
88         for (int i=1; i<=n; i++)
89         {
90             if (dis[i] == INF)
91                 dis[i] = c[i] - 1;
92             printf ("%lld%c", dis[i]-c[i], i==n?'\n':' ');
93         }
94     }
95     return 0;
96 }

 

posted @ 2015-08-09 07:55  罗茜  阅读(542)  评论(2编辑  收藏  举报