以前以为很难,理解起来很简单还是重在运用吧。随便百度就知道,差分约束系统可以用最短路径来求,可是为什么呢:
假设不等式 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; }