题目大意:
在一个一维坐标轴上排列各个点,使得每两个点直接满足给定的两种条件
某两点间的距离不大于某个值,以及某两点距离不小于某个值
具体思路: 注意一个坐标可以有多个点
差分约束,最短路求解
不懂差分约束的,可以参考这篇博客https://blog.csdn.net/whereisherofrom/article/details/78922648
差分约束的条件:
假设标号A
根据差分约束条件建图,然后spfa判负环求最短路,若有负环则输出-1(此处不考虑是否连通图也能ac),无法到达则输出-2,否则输出最短距离,即最大差值。
具体代码:
#include
#include
#include
#include
#include
using namespace std;
int const N = 1000 + 10, M = 2e4 + 10;
int const INF = 0x3f3f3f3f;
int d[N],visit[N],h[N],inq[N];
int n, ml, md, len;
struct Node {
int v, w, next;
}e[M];
void add(int u,int v,int w)
{
e[len].v = v;
e[len].w = w;
e[len].next = h[u];
h[u] = len++;
}
int spfa()
{
memset(visit, 0, sizeof(visit));
memset(d, 0x3f, sizeof(d));
memset(inq, 0, sizeof(inq));
queue<int> q;
d[1] = 0;
q.push(1);
inq[1]++;
while (q.size())
{
int t = q.front();
q.pop();
visit[t] = 0;
for (int i = h[t];~i; i=e[i].next)
{
int v = e[i].v;
int w = d[t] + e[i].w;
if (d[v] > w)
{
d[v] = w;
if (!visit[v]) {
if (inq[v] > n)return -1;
q.push(v);
visit[v] = 1;
inq[v]++;
}
}
}
}
if (d[n] == INF)return -2;
return d[n];
}
int main()
{
memset(h, -1, sizeof(h));
scanf("%d%d%d", &n, &ml, &md);
for (int i = 1; i <= ml; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w); //v-u<=w
}
for (int i = 1; i <= md; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(v, u, -w); //v-u>=w
}
for (int i = 1; i < n; i++)
add(i+1, i, 0); //标号前的点必须排在前面,即Xi<=Xi+1(题意标明,一个坐标可以有多个点)
printf("%d\n", spfa());
return 0;
}