bzoj2834 回家的路

 题目描述

初步思路

   一眼最短路,然后有换乘这种操作,自然想到分层之后连边,每层图中的边,边权为2,层与层之间的边边权为1就好啦?   但是所有的正解都把我否了?! 丝毫不知道错哪儿,可能是题干看错了?   最后惊讶的发现...看错题了(555......)

题目正解

  也是分层图最短路,不过怎么建图时重点。 分横向,纵向两个方向考虑。然后将同行或者同列的节点连边,跑最短路即可。 另外此题有特判情况,如果起点或者重点与换乘站重合,此时横着竖着都需要判,不能只判断一个方向。

代码

  1 #include <queue>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 const int M = 100020;
  7 #define ll long long
  8 #define Min(a, b) ((a) < (b) ? (a) : (b))
  9 #define Max(a, b) ((a) > (b) ? (a) : (b))
 10 int n, m, cnt;
 11 struct node
 12 {
 13     int x, y, idx;
 14     void Read(int p)
 15     {
 16         scanf("%d%d", &x, &y);
 17         idx = p;
 18     }
 19 }a[M];
 20 int head[M], to[M * 10], nex[M * 10], val[M * 10];
 21 bool inq[M][2];
 22 ll f[M * 10], dis[M * 10][2];
 23 deque <pair <int , int > > q;
 24 void addedge(int a, int b, int v)
 25 {
 26     nex[++ cnt] = head[a];
 27     head[a] = cnt;
 28     to[cnt] = b;
 29     f[cnt] = v;
 30 }
 31 bool cmp1(const node &x, const node &y)
 32 {
 33     return x.x == y.x ? x.y < y.y : x.x < y.x;
 34 }
 35 bool cmp2(const node &x, const node &y)
 36 {
 37     return x.y == y.y ? x.x < y.x : x.y < y.y;
 38 }
 39 bool cmp3(const node &x, const node &y)
 40 {
 41     return x.idx < y.idx;
 42 }
 43 pair <int, int > u;
 44 void spfa()
 45 {
 46     while(!q.empty())
 47     {
 48         u = q.front();
 49         q.pop_front();
 50         int tx = u.first;
 51         int p = u.second;
 52         inq[tx][p] = 0;
 53         for(int i = head[tx] ; i ; i = nex[i])
 54         {
 55             int v = to[i];
 56             if(!p && a[tx].x == a[v].x || p && a[tx].y == a[v].y)
 57                 if(dis[v][p] > dis[tx][p] + f[i])
 58                 {
 59                     dis[v][p] = dis[tx][p] + f[i];
 60                     if(!inq[v][p])
 61                     {
 62                         inq[v][p] = 1;
 63                         pair <int, int > tmp;
 64                         tmp = q.front();
 65                         if(q.empty() || dis[tmp.first][p] >= dis[to[i]][p] - 1930) 
 66                                 q.push_front(make_pair(v , p));
 67                         else
 68                             q.push_back(make_pair(v, p));
 69                     }
 70                 }
 71             if(p && a[tx].x == a[v].x || !p && a[tx].y == a[v].y)
 72                 if(dis[v][p ^ 1] > dis[tx][p] + f[i] + 1)
 73                 {
 74                     dis[v][p ^ 1] = dis[tx][p] + f[i] + 1;
 75                     if(!inq[v][p ^ 1])
 76                     {
 77                         inq[v][p ^ 1] = 1;
 78                         pair <int, int > tmp;
 79                         tmp = q.front();
 80                         if(q.empty() || dis[tmp.first][p] >= dis[to[i]][p] - 1930) 
 81                                 q.push_front(make_pair(v , p ^ 1));
 82                         else
 83                             q.push_back(make_pair(v, p ^ 1));
 84                     }
 85                 }
 86         }
 87     }
 88 }
 89 int main()
 90 {
 91     //freopen("2834.in", "r", stdin);
 92     //freopen("2834.out", "w", stdout);
 93     scanf("%d%d", &n, &m);
 94     for(int i = 1 ; i <= m ; i ++)
 95         a[i].Read(i);
 96     a[0].Read(0);
 97     a[m + 1].Read(m + 1);
 98     sort(a, a + m + 2, cmp1);
 99     for(int i = 0 ; i <= m ; i ++)
100         if(a[i].x == a[i + 1].x)
101         {
102             int tre = 2 * (a[i + 1].y - a[i].y);
103             addedge(a[i].idx, a[i + 1].idx, tre);
104             addedge(a[i + 1].idx, a[i].idx, tre);
105         }
106     sort(a, a + m + 2, cmp2);
107     for(int i = 0 ; i <= m ; i ++)
108         if(a[i].y == a[i + 1].y)
109         {
110             int tre = 2 * (a[i + 1].x - a[i].x);
111             addedge(a[i].idx, a[i + 1].idx, tre);
112             addedge(a[i + 1].idx, a[i].idx, tre);
113         }
114     sort(a, a + m + 2, cmp3);
115     memset(dis, 0x3f, sizeof dis);
116     dis[0][0] = dis[0][1] = 0;
117     inq[0][0] = inq[0][1] = 1; 
118     q.push_front(make_pair(0, 0));
119     q.push_back(make_pair(0, 1));
120     spfa();
121     if(Min(dis[m + 1][0], dis[m + 1][1]) == 0x3f3f3f3f3f3f3f3fll)
122         printf("-1");
123     else
124         printf("%lld
" , Min(dis[m + 1][0] , dis[m + 1][1]));
125     return 0;
126 }
View Code

忽略那个双端队列。 因为我之前数组开小导致TLE,我还以为是spfa的锅...... 结果调完之后,发现加上优化比不加都慢.....

总结

  555....调了一下午。 思路WA了一发,代码WA了一波.....  不过题是好题(QAQ)

原文地址:https://www.cnblogs.com/0724-zcsblog/p/11527970.html