挑战程序设计竞赛2.5例题:Layout POJ - 3169
Like everyone else, cows like to stand close to their friends when queuing for feed. FJ has N (2 <= N <= 1,000) cows numbered 1..N standing along a straight line waiting for feed. The cows are standing in the same order as they are numbered, and since they can be rather pushy, it is possible that two or more cows can line up at exactly the same location (that is, if we think of each cow as being located at some coordinate on a number line, then it is possible for two or more cows to share the same coordinate).
Some cows like each other and want to be within a certain distance of each other in line. Some really dislike each other and want to be separated by at least a certain distance. A list of ML (1 <= ML <= 10,000) constraints describes which cows like each other and the maximum distance by which they may be separated; a subsequent list of MD constraints (1 <= MD <= 10,000) tells which cows dislike each other and the minimum distance by which they must be separated.
Your job is to compute, if possible, the maximum possible distance between cow 1 and cow N that satisfies the distance constraints.
Some cows like each other and want to be within a certain distance of each other in line. Some really dislike each other and want to be separated by at least a certain distance. A list of ML (1 <= ML <= 10,000) constraints describes which cows like each other and the maximum distance by which they may be separated; a subsequent list of MD constraints (1 <= MD <= 10,000) tells which cows dislike each other and the minimum distance by which they must be separated.
Your job is to compute, if possible, the maximum possible distance between cow 1 and cow N that satisfies the distance constraints.
Input
Line 1: Three space-separated integers: N, ML, and MD.
Lines 2..ML+1: Each line contains three space-separated positive integers: A, B, and D, with 1 <= A < B <= N. Cows A and B must be at most D (1 <= D <= 1,000,000) apart.
Lines ML+2..ML+MD+1: Each line contains three space-separated positive integers: A, B, and D, with 1 <= A < B <= N. Cows A and B must be at least D (1 <= D <= 1,000,000) apart.
Lines 2..ML+1: Each line contains three space-separated positive integers: A, B, and D, with 1 <= A < B <= N. Cows A and B must be at most D (1 <= D <= 1,000,000) apart.
Lines ML+2..ML+MD+1: Each line contains three space-separated positive integers: A, B, and D, with 1 <= A < B <= N. Cows A and B must be at least D (1 <= D <= 1,000,000) apart.
Output
Line 1: A single integer. If no line-up is possible, output -1. If cows 1 and N can be arbitrarily far apart, output -2. Otherwise output the greatest possible distance between cows 1 and N.
Sample Input
4 2 1 1 3 10 2 4 20 2 3 3
Sample Output
27
Hint
Explanation of the sample:
There are 4 cows. Cows #1 and #3 must be no more than 10 units apart, cows #2 and #4 must be no more than 20 units apart, and cows #2 and #3 dislike each other and must be no fewer than 3 units apart.
The best layout, in terms of coordinates on a number line, is to put cow #1 at 0, cow #2 at 7, cow #3 at 10, and cow #4 at 27.
There are 4 cows. Cows #1 and #3 must be no more than 10 units apart, cows #2 and #4 must be no more than 20 units apart, and cows #2 and #3 dislike each other and must be no fewer than 3 units apart.
The best layout, in terms of coordinates on a number line, is to put cow #1 at 0, cow #2 at 7, cow #3 at 10, and cow #4 at 27.
这道题的关键在于找出题意给与的不等式并进行变形,然后结合图的最短路特性进行求解。
我们知道所有的牛都是按编号排序的,对于关系好的牛满足d[al] + dl >= d[bl] (其中,al < bl),我们可以看成d[bl] - d[al] <= dl,也就是从al到达bl最大花费dl距离,对于d[ad] + dd <= d[bd],则可以化成d[ad] - d[bd] <= -dd,也就是从ad到达bd最大花费-dd距离,我们假设存在d[u] - d[v] <= w(1), d[v] - d[s] <= t(2), d[u] - d[s] <= p(3),那么我们联立(1)(2)得d[u] - d[s] <= w + t(4),联立(3)(4)得:d[u] - d[s] <= min(p, w + t)(5),我们得出对于满足所有条件的情况下,假设v为目标节点,s为出发点,d[u] - d[s]的最大也必定满足所有等式联立成d[u] - d[s] <= x(x为所有联立或者原始的不等式左边为d[u] - d[s] 时,右边值的最小情况(例如x <= 9 && x <= 3,那么x的范围肯定是小于等于最小的3,也就是满足x <= 3)),因此我们与最短路进行对比易得我们求解d[u] - d[s] 的最大实际上就是求解d[u] - d[s] <= x (x为上文所说的意思)的x值(因为d[u] - d[s]一定要满足这些关系),x的值也等于把每个奶牛看成一个节点,两点之间的权重就是题目给的最大值(或者其相反数)也就是dl或者-dd时,从s到u的最短路径(因为d[u] - d[s]可以看成存在一条路径使得s到u,且权值为p,而联立得到的不等式可以看成是从s到达v的最短路径加上v到达u(u,v直接联通)的值,参考最短路径的意义)
#include <queue> #include <stdio.h> #include <algorithm> #include <vector> using namespace std; const int INF = 0x3fffffff; int d[1005];//d[n]为1到n的最短路的值 int n, ml, md; struct Node{ int to;//点 int v;//值 Node(int x, int y){ to = x; v = y; } }; vector<Node> v[1005];//邻接表 queue<int> que;//SPFA队列 int cnt[1005];//每个节点进入队列的次数,如果超过n次这说明有负环也就是无法满足题意 bool in_que[1005];//是否已经在队列中 bool SPFA() { fill(d, d + n + 1, INF);//初始化全不可达 d[1] = 0;//从1到1可达且权值为0 cnt[1] = 1; in_que[1] = true; que.push(1); while(!que.empty()) { int t = que.front(); que.pop(); in_que[t] = false; for(int i = 0; i < v[t].size(); i++) { if(v[t][i].v + d[t] < d[v[t][i].to]) { d[v[t][i].to] = v[t][i].v + d[t]; if(!in_que[v[t][i].to]) { if(++cnt[v[t][i].to] > n)//有负环,不可能满足条件 return false; in_que[v[t][i].to] = true; que.push(v[t][i].to); } } } } return true; } int main(void) { int a, b, dis; scanf("%d %d %d", &n, &ml, &md); for(int i = 0; i < ml; i++) { scanf("%d %d %d", &a, &b, &dis); v[a].push_back(Node(b, dis)); } for(int i = 0; i < md; i++) { scanf("%d %d %d", &a, &b, &dis); v[b].push_back(Node(a, -dis)); } if(!SPFA()) printf("-1\n"); else if(d[n] == INF)//当n为INF,则说明即使无穷远也可以满足条件,则输出-2 printf("-2\n"); else printf("%d\n", d[n]); return 0; }
,所以本题就变成了求解带有负值的最短路问题,我们采用SPFA进行解决。
AC代码: