POJ 2449 Remmarguts’ Date
Posted in PKU OJ on 五月 13th, 2010 by 纳米 – Be the first to comment这道题是五一那天在学校做的。我没有读题,只知道题目意思如下:
输入格式:
n, m
u_1, v_1, w_1
…
u_m, v_m, w_m
s, t, k
求s到t的第k短路。
解题报告:
利用A*搜索,具体此题题解网上一大摞,我就不说了。我是用spfa算最短路和手写堆的,没有用dijkstra和STL的优先级队列(其实是因为不会用STL -_-|||)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | #include <stdio.h> #include <string.h> const int maxn = 1003, maxm = 100003; int n, m, s, t, k, el[maxm][3]; int dist[maxn], heap[maxn*maxn][3], tt; int answer; struct EDGE { int v, l; }; int input() { scanf("%d%d", &n, &m); for (int i = 1; i <= m; ++i) scanf("%d%d%d", &el[i][0], &el[i][1], &el[i][2]); scanf("%d%d%d", &s, &t, &k); if (s == t) ++k; return 0; } int spfa() { EDGE *edge[maxn]; int et[maxn] = {0}; for (int i = 1; i <= m; ++i) ++et[el[i][1]]; for (int i = 1; i <= n; ++i) edge[i] = new EDGE [et[i] + 1]; memset(et, 0, sizeof(et)); for (int i = 1; i <= m; ++i) { int u = el[i][1], v = el[i][0]; edge[u][et[u]].v = v; edge[u][et[u]].l = el[i][2]; ++et[u]; } int q[maxn], head = -1, last = 0; bool vis[maxn] = {0}; q[0] = t; vis[t] = true; for (int i = 1; i <= n; ++i) dist[i] = 0x7FFFFFFF; dist[t] = 0; while (head < last) { int u = q[++head % maxn]; vis[u] = false; for (int i = 0, v = edge[u][0].v; i < et[u]; v = edge[u][++i].v) if (dist[u] + edge[u][i].l < dist[v]) { dist[v] = edge[u][i].l + dist[u]; if (!vis[v]) { q[++last % maxn] = v; vis[v] = true; } } } return 0; } bool empty() { return tt == 0; } void swap(int w0, int w1) { int temp; temp = heap[w0][0]; heap[w0][0] = heap[w1][0]; heap[w1][0] = temp; temp = heap[w0][1]; heap[w0][1] = heap[w1][1]; heap[w1][1] = temp; temp = heap[w0][2]; heap[w0][2] = heap[w1][2]; heap[w1][2] = temp; } void insert(int key0, int key1, int key2) { int t = ++tt; heap[tt][0] = key0; heap[tt][1] = key1; heap[tt][2] = key2; while (t > 1 && heap[t][0] < heap[t >> 1][0]) { swap(t, t >> 1); t >>= 1; } } void keep(int t) { int left = t << 1; int right = left + 1; int mint = t; if (left <= tt) mint = heap[left][0] < heap[mint][0] ? left : mint; if (right <= tt) mint = heap[right][0] < heap[mint][0] ? right : mint; if (mint != t) { swap(mint, t); keep(mint); } } void pop(int &key0, int &key1, int &key2) { key0 = heap[1][0], key1 = heap[1][1], key2 = heap[1][2]; if (tt > 1) { swap(1, tt--); keep(1); } else { tt = 0; } } int work() { EDGE *edge[maxn]; int et[maxn] = {0}, its[maxn] = {0}, ots[maxn] = {0}; for (int i = 1; i <= m; ++i) ++et[el[i][0]]; for (int i = 1; i <= n; ++i) edge[i] = new EDGE [et[i] + 1]; memset(et, 0, sizeof(et)); for (int i = 1; i <= m; ++i) { int u = el[i][0], v = el[i][1]; edge[u][et[u]].v = v; edge[u][et[u]].l = el[i][2]; ++et[u]; } tt = 0; insert(dist[s], s, 0); while (!empty()) { int c, cost, u; pop(c, u, cost); ++ots[u]; if (ots[t] == k) return cost; for (int i = 0, v = edge[u][0].v; i < et[u]; v = edge[u][++i].v) if (ots[v] < k) insert(cost + edge[u][i].l + dist[v], v, cost + edge[u][i].l); for (int i = 0, v = edge[u][0].v; i < et[u]; v = edge[u][++i].v) if (its[v] < k) ++its[v]; } return -1; } int output() { printf("%d\n", answer); return 0; } int main() { input(); spfa(); answer = work(); output(); return 0; } |