题目传送门
这是一条通往vjudge的神秘通道
这是一条通往bzoj的神秘通道
题目大意
如果一条路径走过的边依次为$e_{1}, e_{2}, \cdots , e_{k}$,那么它的长度为$e_{1} + \max (e_{1}, e_{2}) + \max (e_{2}, e_{3}) + \cdots + \max (e_{k - 1}, e_{k}) + e_{k}$,问点$1$到点$n$的最短路。
显然需要把状态记在最后一条边上。
然后给一个菊花图,这个做法就gg了。
因此考虑一些黑科技。
可以把边看成点,然后考虑如何在辺与边之间快速连边。
对于一个点的出边,可以把它们按照权值排序,大的向比它略小的连一条权值为0的边,小的向比它略大的连一天权值为它们边权之差的边。
然后原图中每条边向它的反向边连一条边权相同的边。
然后再建两个虚点,一个起点,向以1为起点的边连边,边权不变。一个终点,以$n$为终点的边向它连边。
Code
1 /** 2 * bzoj 3 * Problem#4289 4 * Accepted 5 * Time: 3200ms 6 * Memory: 31292k 7 */ 8 #include <bits/stdc++.h> 9 #ifndef WIN32 10 #define Auto "%lld" 11 #else 12 #define Auto "%I64d" 13 #endif 14 using namespace std; 15 typedef bool boolean; 16 17 #define ll long long 18 19 typedef class Edge { 20 public: 21 int end, next, w; 22 23 Edge(int end = 9, int next = 0, int w = 0):end(end), next(next), w(w) { } 24 }Edge; 25 26 typedef class MapManager { 27 public: 28 int ce; 29 int *h; 30 Edge *es; 31 32 MapManager() { } 33 MapManager(int n, int m):ce(-1) { 34 h = new int[(n + 1)]; 35 es = new Edge[(m + 5)]; 36 memset(h, -1, sizeof(int) * (n + 1)); 37 } 38 39 void addEdge(int u, int v, int w) { 40 es[++ce] = Edge(v, h[u], w); 41 h[u] = ce; 42 // cerr << u << "->" << v << " " << w << endl; 43 } 44 45 Edge& operator [] (int pos) const { 46 return es[pos]; 47 } 48 }MapManager; 49 50 int n, m; 51 Edge *es; 52 vector<int> *dg; 53 MapManager g; 54 55 inline void init() { 56 scanf("%d%d", &n, &m); 57 es = new Edge[(m + 1)]; 58 dg = new vector<int>[(n + 1)]; 59 for (int i = 0; i < m; i++) { 60 scanf("%d%d%d", &es[i].end, &es[i].next, &es[i].w); 61 dg[es[i].end].push_back(i << 1); 62 dg[es[i].next].push_back(i << 1 | 1); 63 } 64 } 65 66 boolean cmp(const int& a, const int& b) { 67 return es[a >> 1].w < es[b >> 1].w; 68 } 69 70 int s, t; 71 72 inline void build() { 73 g = MapManager((m << 1) + 2, m << 3); 74 s = m << 1, t = m << 1 | 1; 75 for (int i = 1; i <= n; i++) { 76 sort(dg[i].begin(), dg[i].end(), cmp); 77 for (int j = 1; j < (signed) dg[i].size(); j++) { 78 int u = (j) ? (dg[i][j - 1]) : (-1), v = dg[i][j]; 79 g.addEdge(v, u, 0); 80 g.addEdge(u, v, es[v >> 1].w - es[u >> 1].w); 81 } 82 } 83 84 for (int i = 0; i < (signed) dg[1].size(); i++) 85 g.addEdge(s, dg[1][i], es[dg[1][i] >> 1].w); 86 for (int i = 0; i < (signed) dg[n].size(); i++) 87 g.addEdge(dg[n][i] ^ 1, t, es[dg[n][i] >> 1].w); 88 89 for (int i = 0, w; i < m; i++) { 90 w = es[i].w; 91 g.addEdge(i << 1, i << 1 | 1, w); 92 g.addEdge(i << 1 | 1, i << 1, w); 93 } 94 } 95 96 typedef class Node { 97 public: 98 int p; 99 ll dis; 100 101 Node(int p = 0, ll dis = 0):p(p), dis(dis) { } 102 103 boolean operator < (Node b) const { 104 return dis > b.dis; 105 } 106 }Node; 107 108 ll *f; 109 priority_queue<Node> que; 110 inline ll dijstra() { 111 f = new ll[(m << 1) + 2]; 112 memset(f, 0x3f, sizeof(ll) * ((m << 1) + 2)); 113 que.push(Node(s, f[s] = 0)); 114 while (!que.empty()) { 115 Node e = que.top(); 116 que.pop(); 117 if (e.dis != f[e.p]) continue; 118 for (int i = g.h[e.p]; ~i; i = g[i].next) { 119 Node eu (g[i].end, e.dis + g[i].w); 120 if (eu.dis < f[eu.p]) { 121 f[eu.p] = eu.dis; 122 que.push(eu); 123 } 124 } 125 } 126 return f[t]; 127 } 128 129 inline void solve() { 130 printf(Auto"\n", dijstra()); 131 } 132 133 int main() { 134 init(); 135 build(); 136 solve(); 137 return 0; 138 }
原文地址:https://www.cnblogs.com/yyf0309/p/8504265.html
时间: 2024-10-10 04:52:14