差分约束(poj 1201
这里简要记一下差分约束。
所谓差分约束,指的是由a-b>=c这种不等式组组成的约束系统。一般的线性规划问题可以用单纯形法解决,但是这种特殊情况可以借助最短路算法解决。
记源点到v的最短路为d[v],从u到v的最短路为d(u,v)。差分约束的最短路做法基于最短路的以下特点:
对于没有负圈的图,任意两点d[u]+d(u,v)>=d[v],实际上相当于一条从u到v的长度为d的边(类比求最短路的过程,可以知道的d[v]的最终值是(d[u]+d(u,v))的最小值)。
对于约束条件都转化成以上形式连边之后,所求得的d[t]-d[s]也就是d[t]其实就是原约束条件下d[t]-d[s]的最大值。(因为各路径的约束条件中取等号即最短路时差取最大值d(u,v))
对于求最小值的情况,需要转化成d[u]+d(u,v)<=d[v]这样的形式,然后连边求最长路,与最短路时对称。
1201代码:
#include<iostream> #include<map> #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<vector> #include<queue> #include<stack> #include<functional> #include<set> #define pb push_back #define fs first #define se second using namespace std; typedef long long ll; typedef pair<ll,ll> P; const int maxv=5e4+400; struct E{ int t,w; E *next; }es[maxv*4]; int h=0; E *G[maxv]; E *tail[maxv]; void add(int from,int to,int w){ tail[from]->next=&es[h++]; tail[from]->t=to; tail[from]->w=w; tail[from]=tail[from]->next; tail[from]->next=NULL; } int n; int dis[maxv]; int s=maxv,t=0; bool vis[maxv]; queue<int> Q; void BF(int s){ for(int i=s;i<=t;i++) dis[i]=-1e9; dis[s]=0; Q.push(s); vis[s]=1; while(!Q.empty()){ int v=Q.front(); Q.pop(); vis[v]=0; for(E *i=G[v];i->next!=NULL;i=i->next){ E &e=*i; if(dis[e.t]<dis[v]+e.w){ dis[e.t]=dis[v]+e.w; if(!vis[e.t]){ vis[e.t]=1; Q.push(e.t); } } } } cout<<dis[t]<<endl; } int main(){ //////freopen("/home/files/CppFiles/in","r",stdin); cin>>n; for(int i=0;i<maxv;i++){ G[i]=&es[h++]; tail[i]=G[i]; tail[i]->next=NULL; } for(int i=0;i<n;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z);////左闭右开区间 s=min(s,x); t=max(t,y+1); add(x,y+1,z); } for(int i=0;i<maxv-1;i++){ add(i,i+1,0); add(i+1,i,-1); } BF(s); return 0; }
PS:这题卡vector邻接表。。。。