作用
求解多个形如x+y<=c(c为常数)的不等式.
具体做法
可以发现,在求最短路时,若a,b间有边的权值为c,则d[a]+c>=d[b],因而可以将不等式转化为这个形式,之后建边跑最短路即可.
实际应用
一般讲题目转化为多个形如x+y<=c(c为常数)的不等式,之后建图跑最短路.
此题中一共就三种限制:
1.升序排列
2.有两点a,b间的距离不超过k,也就是b-a<=k,可转化为b<=a+k,a向b连一条长度为k的边.
3.有两点a,b间的距离至少为k,也就是b-a>=k,可转化为a<=b-k,b向a连一条长度为-k的边.
最短路,若有负环,则无解,若不连通,则无限制,其余情况,输出d[n].
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define INF 0x3f3f3f3f
#define N 1010
using namespace std;
int n,m,k,bb,first[N],d[N];
bool in[N];
struct Bn
{
int to,next,quan;
}bn[100100];
queue<int>que;
inline void add(int u,int v,int w)
{
bb++;
bn[bb].to=v;
bn[bb].next=first[u];
bn[bb].quan=w;
first[u]=bb;
}
int main()
{
memset(first,-1,sizeof(first));
int i,j,p,q,o;
cin>>n>>m>>k;
for(i=2;i<=n;i++)
{
add(i,i-1,0);
}
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&p,&q,&o);
if(p>q) swap(p,q);
add(p,q,o);
}
for(i=1;i<=k;i++)
{
scanf("%d%d%d",&p,&q,&o);
if(p>q) swap(p,q);
add(q,p,-o);
}
memset(d,INF,sizeof(d));
que.push(1);
d[1]=0;
for(;!que.empty();)
{
if(d[q]<0)
{
puts("-1");
return 0;
}
q=que.front();
que.pop();
in[q]=0;
for(p=first[q];p!=-1;p=bn[p].next)
{
if(d[bn[p].to]>d[q]+bn[p].quan)
{
d[bn[p].to]=d[q]+bn[p].quan;
if(!in[bn[p].to])
{
in[bn[p].to]=1;
que.push(bn[p].to);
}
}
}
}
d[n]==INF?puts("-2"):printf("%d",d[n]);
}