这个题同样是差分约束,求的是最矮的树和最高的树之间的最大距离,注意有一个坐标的先后关系在起作用,所以我们要想方法将数B究竟在树A左边还是右边用不同的边权表示出来,所以,B在A的左边,就从B向A连一条边(单向),C在A的右边,就从A向C连一条边,对于起点、终点两个点,最后只要求靠左边的那个点到右边的那个点的最短路就可以了。516ms
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#define N 1010
#define M 3500
#define MAXQ 3500
using namespace std;
const int inf = (-1u >> 1);
int d[N], first[N];
int v[M] , w[M], next[M];
bool inq[N];
int cnt[N];
int e;
int q[MAXQ];
int indx[N];
int t[N];
void addE(int x, int y, int c)
{
next[e] = first[x], first[x] = e;
v[e] = y;
w[e] = c;
e++;
}
bool cmp(int a, int b)
{
return t[a] < t[b];
}
bool SPFA(int s, int t, int n)
{
for (int i = 0; i < n; i++)d[i] = inf;
memset(cnt, 0, sizeof(cnt));
d[s] = 0;
int qs, qe;
qs = qe = 0;
for (int i = 0; i < n; i++)inq[i] = false;
q[qe++] = s;
while (qs != qe)
{
int x = q[qs];
inq[x] = false;
for (int e = first[x]; e != -1; e = next[e])if (d[v[e]] > d[x] + w[e])
{
d[v[e]] = d[x] + w[e];
if (!inq[v[e]])
{
inq[v[e]] = true;
q[qe++] = v[e];
if (qe == MAXQ)qe = 0;
if (++cnt[v[e]] >= n)return false;
}
}
qs++;
if (qs == MAXQ)qs = 0;
}
return true;
}
int main()
{
int n, D;
// FILE* fp = fopen("in.txt", "r");
while (scanf( "%d %d", &n, &D) != EOF && (n + D))
{
e = 0;
for (int i = 0; i < n; i++)first[i] = -1;
for (int i = 0; i < n; i++)
{
scanf( "%d", t+i);
indx[i] = i;
}
sort(indx, indx + n, cmp);
// for (int i = 0; i < n; i++) printf("%d ", indx[i]);puts("");
int start = indx[0];
int end = indx[n - 1];
for (int i = 0; i < n - 1; i++)
{
int a = indx[i], b = indx[i + 1];
if (a < b)
addE(a, b, D);
else
addE(b, a, D);
addE(i + 1, i, -1);
}
if (start > end)start ^= end, end ^= start, start ^= end;
if (SPFA(start, end, n))printf("%d\n", d[end]);
else puts("-1");
// getchar();getchar();
}
return 0;
}