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\n" , Min(dis[m + 1][0] , dis[m + 1][1])); 125 return 0; 126 }
忽略那个双端队列。 因为我之前数组开小导致TLE,我还以为是spfa的锅...... 结果调完之后,发现加上优化比不加都慢.....
总结
555....调了一下午。 思路WA了一发,代码WA了一波..... 不过题是好题(QAQ)