差分约束(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;

}
View Code

PS:这题卡vector邻接表。。。。

你可能感兴趣的:(差分约束)