Arkady likes to walk around his kitchen. His labyrinthine kitchen consists of several important places connected with passages. Unfortunately it happens that these passages are flooded with milk so that it's impossible to pass through them. Namely, it's possible to pass through each passage in any direction only during some time interval.
The lengths of all passages are equal and Arkady makes through them in one second. For security reasons, Arkady can never stop, also, he can't change direction while going through a passage. In other words, if he starts walking in some passage, he should reach its end and immediately leave the end.
Today Arkady needs to quickly reach important place n from place 1. He plans to exit the place 1 at time moment 0 and reach the place nas early as he can. Please find the minimum time he should spend on his way.
The first line contains two integers n and m (1 ≤ n ≤ 5·105, 0 ≤ m ≤ 5·105) — the number of important places and the number of passages, respectively.
After that, m lines follow, each of them describe one passage. Each line contains four integers a, b, l and r (1 ≤ a, b ≤ n, a ≠ b, 0 ≤ l < r ≤ 109) — the places the passage connects and the time segment during which it's possible to use this passage.
Print one integer — minimum time Arkady should spend to reach the destination. If he can't reach the place n, print -1.
5 6 1 2 0 1 2 5 2 3 2 5 0 1 1 3 0 1 3 4 1 2 4 5 2 3
3
2 1 1 2 1 100
-1
In the first example Arkady should go through important places 1 → 3 → 4 → 5.
In the second example Arkady can't start his walk because at time moment 0 it's impossible to use the only passage.
题意:给一个图,每条边有一个出现时间[l, r],边权都为1,必须一直走,求1到n最短路
题解:
DP
想到DP边就好做多了,按时间奇偶和方向拆边
首先用一个堆维护边的DP值,然后它可以更新反向边,然后同向的边按照l排序之后有单调性,直接更新就好了
#include
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair < int, int > pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 500005;
const int INF = 0x3f3f3f3f;
struct Node { int v, x, t, i; bool operator < (const Node &b) const { return v > b.v; } };
struct Edge { int p, l, r, v; };
int n, m, cur[MAXN][2];
vector < Edge > G[MAXN];
vector < pii > adj[MAXN][2];
vector < int > f[MAXN][2];
priority_queue < Node > Q;
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
n = Read(), m = Read();
if (n == 1)
return puts("0"), 0;
for (int i = 1, u, v, l, r; i <= m; i ++)
u = Read(), v = Read(), l = Read(), r = Read(), G[u].pb({v, l, r, G[v].size()}), G[v].pb({u, l, r, G[u].size() - 1});
for (int i = 1; i <= n; i ++)
for (int j = 0; j < 2; j ++)
{
f[i][j].resize(G[i].size(), INF);
for (int k = 0; k < G[i].size(); k ++)
adj[i][j].pb(mp(G[i][k].l + ((G[i][k].l & 1) ^ j), k));
sort(adj[i][j].begin(), adj[i][j].end());
}
for (int i = 0; i < G[1].size(); i ++)
if (!G[1][i].l)
f[1][0][i] = 0, Q.push({0, 1, 0, i});
while (!Q.empty())
{
Node tmp = Q.top(); Q.pop();
int x = tmp.x, t = tmp.t, p = tmp.i, r = G[x][p].v, y = G[x][p].p, v = f[x][t][p], d = G[x][p].r - ((G[x][p].r & 1) ^ t);
if (tmp.v > v)
continue;
//printf("%d %d %d %d\n", x, t, p, v);
if (f[y][t ^ 1][r] > v + 1 && G[x][p].l <= v + 1 && G[x][p].r >= v + 1)
f[y][t ^ 1][r] = v + 1, Q.push({v + 1, y, t ^ 1, r});
if (v > d)
continue;
while (cur[x][t] < G[x].size())
{
pii g = adj[x][t][cur[x][t]];
if (g.xx > d)
break;
if (max(g.xx, v) < f[x][t][g.yy])
f[x][t][g.yy] = max(g.xx, v), Q.push({max(g.xx, v), x, t, g.yy});
cur[x][t] ++;
}
}
int ans = INF;
for (int i = 0; i < G[n].size(); i ++)
for (int j = 0; j < 2; j ++)
ans = min(ans, f[n][j][i]);
if (ans == INF)
ans = -1;
return printf("%d\n", ans), 0;
}