差分约束系统小结


在一个差分约束系统中,线性规划矩阵A的每一行包含一个1和一个-1,A的其他所有元素都为0。因此,由Ax≤b给出的约束条件是m个差分约束集合,其中包含n个未知量,对应的线性规划矩阵A为m行n列。每个约束条件为如下形式的简单线性不等式:xj-xi≤bk。其中1≤i,j≤n,1≤k≤m。
 在一个差分约束系统Ax≤b中,m X n的线性规划矩阵A可被看做是n顶点,m条边的图的关联矩阵。对于i=1,2,…,n,图中的每一个顶点vi对应着n个未知量的一个xi。图中的每个有向边对应着关于两个未知量的m个不等式中的一个。


   给定一个差分约束系统Ax≤b,相应的约束图是一个带权有向图G=(V,E),其中V={v0,v1,…,vn},而且E={ (vi,vj) : xj-xi≤bk是一个约束}∪{ (v0,v1) , (v0,v2) , … , (v0,vn) }。引入附加顶点v0是为了保证其他每个顶点均从v0可达。因此,顶点集合V由对应于每个未知量xi的顶点vi和附加的顶点v0组成。边的集合E由对应于每个差分约束条件的边与对应于每个未知量xi的边(v0,vi)构成。如果xj-xi≤bk是一个差分约束,则边(vi,vj)的权w(vi,vj)=bk(注意i和j不能颠倒),从v0出发的每条边的权值均为0。


具体做法:


对于差分不等式xj-xi<=bk建一条xi到xj的权为bk的边,求的是最短路,获得的是最大值;对于不等式xj-xi>=bk建一条xi到xj的权为bk的边,求的是最长路,获得的是最小值。


poj1716 代码


#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<string>
#include<map>
#include<cmath>
using namespace std;

#define INF 0xfffffff

const int maxn=10005;

int head[maxn],dist[maxn],in[maxn],vis[maxn];
int n,m,u,v,s,t,tot;

struct node{
    int v,c,next;
}e[maxn*3];

void add(int u,int v,int c){
    e[tot].v=v;
    e[tot].c=c;
    e[tot].next=head[u];
    head[u]=tot++;
}

void init(){
    memset(head,-1,sizeof(head));
    tot=0;
}

int spfa(){
    memset(in,0,sizeof(in));
    memset(vis,0,sizeof(vis));
    for(int i=s;i<=t;++i) dist[i]=-INF;
    dist[s]=0;
    queue<int> que;
    que.push(s);
    vis[s]=1;
    while(!que.empty()){
        int top=que.front();
        que.pop();
        vis[top]=0;
        for(int i=head[top];i!=-1;i=e[i].next){
            v=e[i].v;
            if(dist[v]<dist[top]+e[i].c){
                dist[v]=dist[top]+e[i].c;
                if(!vis[v]){
                    vis[v]=1;
                    que.push(v);
                }
            }
        }
    }
    return dist[t];
}
int main()
{
    ios::sync_with_stdio(0);
    int mn,mx;
    while(cin>>m){
        init();
        mx=0;
        mn=INF;
        for(int i=0;i<m;++i){
            cin>>u>>v;
            u++;v++;
            mx=max(mx,v+1);
            mn=min(mn,u);
            add(u,v+1,2);
        }
        for(int i=mn;i<mx;i++){
            add(i,i+1,0);
            add(i+1,i,-1);
        }
        s=mn;t=mx;
        cout<<spfa()<<endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值