题意:
给定一些点,给定一些关系(两点之间的距离大于某个值或小于某个值),求1号点与N号点之间的最大距离,无解输出-1,任意距离均能成立输出-2。
差分约束系统。对于两个点A,B之间距离不超过D,用数学方法表示即 B - A > D,反之则为 A - B > D , 可以用差分约束系统来处理这种关系,由于由差分约束得到的一组解加 K 仍然成立,所以说解中 dist[n] - dist[1] 总是为定值,当 dist[1] = 0 时,所求解即为 dist[n] , 所以说一次以 1 号点为起点的最短路就可以得到解。
#include<iostream>
#include<cmath>
#include<cstdio>
#include<deque>
using namespace std;
const int size = 200010;
int head[size],next[size],dist[size];
int tim[size];
bool use[size];
struct dc
{
int t,d;
}l[size];
int tot = 1;
void build(int f,int t,int d)
{
l[tot].t = t;
l[tot].d = d;
next[tot] = head[f];
head[f] = tot ++;
}
int n,ml,md;
deque < int > q;
bool spfa(int s)
{
for(int i = 1 ; i <= n ; i ++)
dist[i] = 214748364;
dist[s] = 0;
use[s] = 1;
q.push_back(s);
while(!q.empty())
{
int f = q.front();
q.pop_front();
use[f] = 0;
for(int i = head[f] ; i ; i = next[i])
{
int t = l[i].t;
if(dist[t] > dist[f] + l[i].d)
{
dist[t] = dist[f] + l[i].d;
if(!use[t])
{
tim[t] ++;
use[t] = 1;
if(!q.empty())
{
if(dist[t] < dist[q.front()])
q.push_front(t);
else if(t > q.front())
q.push_front(t);
else
q.push_back(t);
}
else
q.push_back(t);
if(tim[t] >= n)
return false;
}
}
}
}
return true;
}
int main()
{
scanf("%d%d%d",&n,&ml,&md);
for(int i = 1 ; i <= ml ; i ++)
{
int f,t,d;
scanf("%d%d%d",&f,&t,&d);
build(f,t,d);
}
for(int i = 1 ; i <= md ; i ++)
{
int f,t,d;
scanf("%d%d%d",&f,&t,&d);
build(t,f,-d);
}
if(!spfa(1))
puts("-1");
else if(dist[n] == 214748364)
puts("-2");
else
cout<<dist[n];
return 0;
}
传送门 : codevs1242