【最短路/线性差分约束】Layout POJ - 3169
Layout POJ - 3169
题意:
\(n\)头奶牛按序号\(1~n\)排成一行,允许多头奶牛站在同一个位置上。给定\(ML\)行关系,每行三个整数\(u,v,dis\),表示奶牛\(u\)与奶牛\(v\)的距离不大于\(dis\);再给定\(MD\)行关系,每行三个整数\(u,v,dis\),表示奶牛\(u\)与奶牛\(v\)的距离不小于\(dis\)。求奶牛\(n\)与奶牛\(1\)的最大可能距离。
如果最大可能距离不存在,输出\(-1\);如果最大可能距离可以是任意值,输出\(-2\);否则输出这个距离。
思路:
线性差分约束,所求的是最大值。因此答案就是从节点\(1\)到节点\(n\)的最短路。
所给出的约束关系都应该为\(u-v≤d\)的形式。
对于其中\(MD\)行约束关系,给出的是\(u-v≥d\),因此等号两边同乘\(-1\)变形得\(v-u≤-d\)。
由此可见根据约束关系所建的图包含负权边,即可能存在负权环,对应的是最大可能距离不存在的情况;如果奶牛\(n\)与奶牛\(1\)之间没有直接或间接的约束关系,也就是节点\(n\)不可到达,对应的是最大可能距离可以是任意值的情况。
const int INF = 0x3f3f3f3f3f;
const int maxn = 1000 + 10;
int num = 0;
int n, m;
int head[maxn], inq_cnt[maxn];
LL d[maxn];
bool inq[maxn];
struct Edge {
int next, to;
LL dis;
}edges[maxn*20];
void add_edge(int from, int to, LL dis) {
num++;
edges[num].next = head[from];
edges[num].to = to;
edges[num].dis = dis;
head[from] = num;
}
bool spfa(int s) {
queue<int> q;
d[s] = 0;
inq[s] = true;
q.push(s);
inq_cnt[s]++;
while (!q.empty()) {
int u = q.front(); q.pop();
inq[u] = false;
for (int i = head[u]; i != 0; i = edges[i].next) {
Edge& e = edges[i];
if (d[u] < INF && d[u] + e.dis < d[e.to]) {
d[e.to] = d[u] + e.dis;
if (!inq[e.to]) {
if (inq_cnt[e.to] > n) return false;
q.push(e.to);
inq[e.to] = true;
inq_cnt[e.to]++;
}
}
}
}
return true;
}
void init() {
num = 0;
memset(edges, 0, sizeof(edges));
memset(inq_cnt, 0, sizeof(inq_cnt));
memset(inq, false, sizeof(inq));
memset(head, 0, sizeof(head));
for (int i = 0; i <= n; i++) d[i] = INF;
}
int main()
{
ios::sync_with_stdio(false);
// FILE* stream1;
// freopen_s(&stream1, "input.txt", "r", stdin);
// freopen_s(&stream1, "output.txt", "w", stdout);
// int t; cin >> t; for(int kase=1;kase<=t;kase++) {
int ml, md;
cin >> n >> ml >> md;
init();
for (int i = 1; i <= ml; i++) {
int u, v;
LL dis;
cin >> u >> v >> dis;
//v-u<=dis;
add_edge(u, v, dis);
// printf("%d→%d:%lld\n", u, v, dis);
}
for (int i = 1; i <= md; i++) {
int u, v;
LL dis;
cin >> u >> v >> dis;
//v-u>=dis
//u-v<=-dis
add_edge(v, u, -dis);
// printf("%d→%d:%lld\n", v, u, -dis);
}
if (!spfa(1)) cout << "-1";
else {
if (d[n] == INF) cout << "-2";
else cout << d[n] - d[1];
}
// }
return 0;
}