Test instructions
A direction graph of n points M is given, and the strict K short circuit of the point 1 to N is obtained.
n<=10000,m<=100000,k<=10000
Benquan <=10000;
Link
Exercises
This is a seemingly classic problem, but the ordinary A * algorithm will be card;
The worst-case complexity will reach O (SPFA (n,m) +kmlog (k+m)) (approximate);
So the algorithm also needs to be optimized;
The main algorithm is Yu-li in the "heap can be persistent" in the paper;
The specific solution is described in the paper;
I just used a persistent left-biased tree to achieve the persistence of the heap;
The algorithm that I understand is that all non-shortest paths are jumping from the non-tree edge of the shortest path tree;
Here the non-tree edge on the mentioned sidetracks;
In order to ensure the establishment of the path, the two adjacent non-tree edges should satisfy the "Nature 1";
The transformation of such problems is very ingenious;
And then the search process and other A * search K big value what is very similar (or else and this similar?) ;
The current state is the selected Benquan and the last selected edge;
can be transferred to the State and other problems are similar (perhaps can see this problem to understand: Contest Hunter-ovoo)
Time complexity This is very fast, is O (SPFA (n,m) +MLOGM+KLOGM) bar = =, anyway, is a log;
However, Konjac Konjac still do not understand the space, so wrote the pointer version (probably O (M+KLOGM) what ghost);
Code:
#include <queue> #include <stdio.h> #include <string.h> #include <algorithm> #define N 11000# Define M 110000#define pr pair<ll,heap*>using namespace std;typedef long long ll;struct heap{heap *l, *r;ll val;int Dis, no;heap ();} *null = new Heap (), *h[n];heap::heap () {L = r = Null;val = no = 0;} heap* Insert (heap* x, heap* y) {if (x = = NULL | | y = = NULL) return x = = null? y:x;if (X->val > Y->val) swap (x, y) ; x->r = Insert (X->r, y), if (X->l->dis < X->r->dis) Swap (x->l, x->r); X->dis = x->r-> Dis + 1;return x;} heap* Merge (heap* x, heap* y) {if (x = = NULL | | y = = NULL) return x = = null? y:x;if (X->val > Y->val) swap (x, y); heap* p = new Heap (), *p = *x;p->r = Merge (P->r, y), if (P->l->dis < P->r->dis) Swap (p->l, p->r);p ->dis = P->r->dis + 1;return p;} ll Dis[n], Val[m];int next[m], from[m], to[m], head[n], pre[n], N, Tot;bool Inq[n], Ist[m];queue<int>q;priority_que UE<PR, vector<pr>, greater<pr> >poq;void Add (int x, int y, ll v) {To[++tot] = Y;val[tot] = V;from[tot] = X;next[tot] = head[x];h EAD[X] = tot;} void Spfa () {int x, y, i;memset (dis, 0x3f, sizeof (DIS)), Q.push (n);d is[n] = 0, Inq[n] = 1;while (!q.empty ()) {x = Q.front (), Q.pop (); inq[x] = 0;for (i = head[x]; i; i = Next[i]) {if (dis[y = To[i] > dis[x] + val[i]) {dis[y] = Dis[x] + val[i];ist [Pre[y]] = 0;ist[pre[y] = i] = 1;if (!inq[y]) inq[y] = 1, Q.push (y);}}} void Build () {Q.push (n); int x, y, i;for (i = 1; I <= tot; i++) {if (ist[i]) continue;y = to[i];heap* temp = new Heap (); TEM P->no = i, Temp->val = Val[i] + dis[from[i]]-dis[to[i]]; H[y] = Insert (h[y], temp);} while (!q.empty ()) {x = Q.front (), Q.pop (); for (i = head[x]; i; i = Next[i]) {y = to[i];if (Ist[i]) {H[y] = merge (H[y], h[x]) ; Q.push (y);}}} void Init () {null->l = Null->r = Null;null->val = Null->no = 0;null->dis = -1;for (int i = 1; I <= N; i++ ) h[i] = null;} int main () {int M, I, J, K, X, Y;ll V, ans;heap* now;scanf ("%d%d%d ", &n, &m, &k); init (); for (i = 1; I <= m; i++) {scanf ("%d%d%lld ", &x, &y, &v); Add (y, x, v);} SPFA (); Build ();p Oq.push (pr (h[1]->val, h[1])); for (i = 1, ans = 0; i < K; i++) {ans = Poq.top (). First, now = Poq.top (). Second ;p Oq.pop (), v = now->val;heap* temp = Merge (Now->l, now->r), if (temp! = null) {Poq.push (pr (ans-v + temp->val, temp));} Poq.push (pr (ans + h[from[now->no]]->val, h[from[now->no]));} printf ("%lld\n", ans + dis[1]); return 0;}
2978: K Short Circuit (strong)