【最短路/線性差分約束】Layout POJ - 3169
阿新 • • 發佈:2020-08-02
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; }