S - Layout (最短路&&差分约束)

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.

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.

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.
先讲一下什么是差分约束(有最短路基础):
一、
1、比如一个二元方程组x-y<=w
我们最短路的转移方程是当d[x]>d[y]+w[y->x]成立的时候就会对d[x]重新赋值
而那个二元方程组是当x-y>w的时候才会用到这个方程组来限制
左右移项得到:x>y+w这个条件是不是和最短路的判断条件一样
这就相当与有一条y--->x长为w的边
2、再看一个二元方程组:x-y>=w
我们可以使他的左右两边同时乘与-1,就会转成上一个情况y-x<=-w
这个是当y>x+(-w)的时候才会用到
另外我们还可以按上一个写
这个式子当x-y<w的时候才会用到
左右移项得到:y>x-w
我们发现这两种方法得到的答案一样,所以我们再转移方程的时候可以用左右都乘与-1的方法来使所有方程的符号都一样
3、当出现等号的时候,如果w得知只能取到整数,即x==y
我们可以用两个方程组来代替它
x-y>=0
y-x>=0
然后把他们的符号和题目中其他方程组的符号化为一致就可以了
而、
我们采用这样的方法可以建立一个图,关于这个图的解,有以下三种模式
1、有解,从方程组中可以得到从起点到终点值
2、存在负环,这个样子从起点到终点的距离就无法算出来
3、从起点到终点没有直接或间接连在一起
可见,只有第一种模式才可以算出来结果
可以说本题了。。。。
 
 
题意:题目给出了两种限制条件,第一种是给出的两头牛之间的距离不得超过一定的距离,第二种是必须超过给出的距离,而且这n头牛是按顺序排队的
提取信息:
x:第一头牛
y:第二头牛
第一种:y-x<=w
第二种:y-x>=w
第三:X(i+1)>=X(i)
我们可以把它们的符号都化为一样的
(1)、把他们都转化为<=
1、y-x<=w    <===>   y<=w+x
2、y-x>=w    <===>   x-y<=-w  <===>   x<=y-w
3、X(i+1)>=X(i)   <===>   X(i)<=X(i+1)+0
抽象一下:d[u]<=d[v]+w[v-->u]
当d[u]>d[v]+w[v-->u] 的是侯才会使用这个式子
那就建立一条v------->u值为w的边
那么1、------------>w[x--->y]=w;
       2、------------->w[y--->x]=-w;
       3、------------->w[(i+1)--->i]=0;
就按照这个建图就可以了?
代码:
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<queue>
 6 using namespace std;
 7 const int INF=0x3f3f3f3f;
 8 int d[1005],dis[1005];
 9 struct shudui
10 {
11     int start,value;
12 }str1;
13 vector<shudui>w[1005];
14 queue<int>r;
15 int main()
16 {
17     int n,m,k;
18     scanf("%d%d%d",&n,&m,&k);
19     while(m--)
20     {
21         int x,y,z;
22         scanf("%d%d%d",&x,&y,&z);
23         str1.start=y;
24         str1.value=z;
25         w[x].push_back(str1);
26     }
27     while(k--)
28     {
29         int x,y,z;
30         scanf("%d%d%d",&x,&y,&z);
31         str1.start=x;
32         str1.value=-z;
33         w[y].push_back(str1);
34     }
35     for(int i=1;i<n;++i)
36     {
37         str1.start=i;
38         str1.value=0;
39         w[i+1].push_back(str1);
40     }
41     memset(d,INF,sizeof(d));
42     r.push(1);
43     r.push(1);
44     d[1]=0;
45     int flag=0;
46     while(!r.empty())
47     {
48         int x=r.front();
49         r.pop();
50         int y=r.front();
51         r.pop();
52         dis[x]=0;
53         if(y>n)
54         {
55             flag=1;
56             break;
57         }
58         int len=w[x].size();
59         for(int i=0;i<len;++i)
60         {
61             str1=w[x][i];
62             if(d[str1.start]>d[x]+str1.value)
63             {
64                 d[str1.start]=d[x]+str1.value;
65                 if(dis[str1.start]) continue;
66                 r.push(str1.start);
67                 r.push(y+1);
68             }
69         }
70     }
71     if(d[n]!=INF && !flag)
72     printf("%d\n",d[n]);
73     else if(d[n]==INF) printf("-2\n");
74     else if(flag) printf("-1\n");
75     return 0;
76 }
View Code

我们还要考虑个问题

本题是让我们求最大值,但是我们建图后为什么求最短路而不是求最长路?

参考博客:https://www.cnblogs.com/cenariusxz/p/4785284.html

首先,我们在最短路初始化的时候所有点的dis值均为INF(极大值),也就是说一开始我们认为n点距离1点是无穷大的。

而对于某一条边 d[v] ≤ d[u] + w(即使≥的也是从这个式子转化而成的),也就是u和v之间距离不能超过w这个条件,只会在d[v] > d[u] + w的时候即u和v之间距离超过w时才会被用来松

弛,而松弛的结果也是使两点距离变成可接受范围内的最大值w,也就是每个边只是松弛到可接受范围内的最大值的。

如果u和v之间的距离已经被其他约束条件限制而小于w了,那么这个条件也就不会起作用也不会使其值更小了,因此最短路求的就是可接受范围内1到n距离的最大值了。

 

如果是 d[u] - d[v] < w,一般利用整数的情况,就是 d[u] - d[v] ≤ w - 1,也可以顺利建图。

如果是 d[u] - d[v] > w,则建立 d[v] - d[u] ≤ -w-1。

 

建图之后最大值求最短路,最小值求最长路即可。

更多差分约束题目见:https://blog.csdn.net/whereisherofrom/article/details/78922648

 
 
 
 

转载于:https://www.cnblogs.com/kongbursi-2292702937/p/10809118.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值