在一个差分约束系统中,线性规划矩阵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;
}