以前以为很难,理解起来很简单还是重在运用吧。随便百度就知道,差分约束系统可以用最短路径来求,可是为什么呢:
假设不等式 x1-x2<=d => x1<=x2+d,这种形式是不是很像最短路径中的更新操作,当x1>x2+d 的时候就必须更新 即d[u]>d[v]+w的时候就要松弛时一样的道理。
这道题的题意很好理解我们只要找到两个约束条件:
Sbi+1-Sai>=ci;
1>= Si+1-Si >=0;(Si+1-Si>=0; Si-Si+1>=-1)
注意这里是>=也就是如果是<就要更新,那么是不是最长路呢。
其中Si,是表示,[0,i-1]这个区间和我们要求的序列的共同值的个数,为什么要加1,是避免0的情况。
代码:
#include<iostream>
#include<vector>
#include<queue>
#include<cmath>
#define maxn 50005
using namespace std;
struct Edge
{
int v,w;
Edge(int x,int y):v(x),w(y){}
};
vector<Edge> vec[maxn];
int dist[maxn];
bool inque[maxn];
void SPFA(int s,int t)
{
int v,w,i;
queue<int> que;
memset(dist,-1,sizeof(dist));
memset(inque,false,sizeof(inque));
while( !que.empty()) que.pop();
dist[s]=0, que.push(s), inque[s]=true;
while( !que.empty()){
s=que.front();
que.pop();
inque[s]=false;
for( i=0;i<vec[s].size();i++){
v=vec[s][i].v,w=vec[s][i].w;
if( dist[v]<dist[s]+w){
dist[v]=dist[s]+w;
if( !inque[v]){
inque[v]=true;
que.push(v);
}
}
}
}
}
int main()
{
int mm,mx,n,i,a,b,c;
while( scanf("%d",&n)!=EOF){
mx=0,mm=maxn;
for( i=0;i<n;i++){
scanf("%d%d%d",&a,&b,&c);
++b;
if( mm>a) mm=a;
if( mx<b) mx=b ;
vec[a].push_back(Edge(b,c));
}
// printf("%d %d\n",mm,mx);
for( i=mm;i<mx;i++){
vec[i].push_back(Edge(i+1,0));
vec[i+1].push_back(Edge(i,-1));
}
SPFA(mm,mx);
printf("%d\n",dist[mx]);
}
return 0;
}