好好写作业!
题意:
农夫约翰又有一群屌屌的奶牛,他们在一条线上吃东西,按照编号(从1到n)排序,有些牛互相之间不喜欢,他们希望之间的距离大于一个值,有些牛关系很好,他们希望吃东西的时候距离不超过一个值。在线上的一个点上可以有多只牛排队。
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.
之前觉得很难很难的题,看题解也不懂,现在再看其实不难,就是个差分约束,感觉区域赛这种级别的比赛不会考裸算法,如果考最短路一定是在途中求一个最短路,或者像这个题一样,差分约束。
下列不等式默认j>i
根据按编号排序,有x[j]>=x[i]
根据ML,有d+x[i]>=x[j]
根据MD,有-d+x[j]>=x[i]
这样就得到了建立差分约束的边:从j到i,长为0;从i到j,长为d;从j到i,长为-d
用SPFA或者bellman即可
如果出现负环,则说明从i到j再到i存在负环,就说明存在冲突。
如果跑完SPFA,dist[n-1]仍为inf,则说明对它没有限制。
否则输出dist[n-1]即可
一开始只有一个错误,就是在SPFA时有的松弛没有进行,因为判读被松弛的点在队列里,但实际上这样可能会错过一些必须的松弛操作,应当判断是否在队列里选择是否入队,而不考虑是否松弛。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
#define mxn 1010
#define inf 0x3f3f3f3f
int mapp[mxn][mxn];
int n,ml,md;
int dist[mxn];
bool spfa(){
queue<int> q;
bool flag[mxn];
int count[mxn];
memset(dist,0x3f,sizeof(dist));
while(!q.empty()) q.pop();
memset(flag,false,sizeof(flag));
memset(count,0,sizeof(count));
q.push(0);
dist[0]=0;
while(!q.empty()){
int now=q.front();
if(count[now]>n) return false;
q.pop();
flag[now]=false;
for(int i=0;i<n;++i) if(dist[now]+mapp[now][i]<dist[i]){
dist[i]=dist[now]+mapp[now][i];
if(flag[i]) continue;
q.push(i);
++count[i];
flag[i]=true;
}
}
return true;
}
int main(){
while(scanf("%d%d%d",&n,&ml,&md)!=EOF){
memset(mapp,0x3f,sizeof(mapp));
for(int i=0;i<n-1;++i)
mapp[i+1][i]=0;
int a,b,d;
for(int i=0;i<ml;++i){
scanf("%d%d%d",&a,&b,&d);
mapp[a-1][b-1]=d;
}
for(int i=0;i<md;++i){
scanf("%d%d%d",&a,&b,&d);
mapp[b-1][a-1]=-d;
}
bool ok=spfa();
if(!ok) puts("-1");
else if(dist[n-1]==inf) puts("-2");
else printf("%d\n",dist[n-1]);
}
return 0;
}