POJ--1201[Intervals] 基础的差分约束

来源:互联网 发布:linux显示乱码 编辑:程序博客网 时间:2024/04/29 23:58
题目大意:

给出N个整数区间[ai,bi],并且给出一个约束ci,( 1<= ci <= bi-ai+1),使得数组Z在区间[ai,bj]的个数>= ci个,求出数组Z的最小长度。

 

分析:

对于给定的条件,假设S[j]为数组Z在[0,j]上的包含的元素个数,则我们可以根据条件得到S[bi+1] - S[ai] >= ci ===> S[ai] - S[bi+1] <= -ci,而且我们在根据隐含的条件1 >= S[j+1]-S[j] >= 0,可以得到一个差分约束系统。但是题目要求我们的是求约束图的最长路径,则我们应该反过来做,令S[N] = 0,从终点开始求。 


若要满足不等式V(a)<=V(b)+W(b,a),则可以从b到a连一条权为W(b,a)的边,求最短路得之。

从b到a的最短路意味着满足所有不等式的a-b之最大值。

即a-b<=w =》b-a>=-w,所有-w就是所求的ans

 

 

CODE:

/*差分约束*//*AC代码:375ms*/#include <iostream>#define MAXN 50005#define INF 0x7fffffffusing namespace std;struct edge{int to,w,next; }E[3*MAXN];int head[MAXN],ecnt;int Stack[MAXN],dis[MAXN],cnt[MAXN];bool Instack[MAXN];int N,top,l,r;void Insert(int from,int to,int w){E[ecnt].to=to;E[ecnt].w=w;E[ecnt].next=head[from];head[from]=ecnt++; }bool Relax(int from,int to,int w){if(dis[to]>dis[from]+w){dis[to]=dis[from]+w;return true; } return false;}void Init(){int i,u,v,w;memset(head,-1,sizeof(head));ecnt=0;l=INF;r=-INF;//S[u]-S[v+1]<=-wfor(i=1;i<=N;i++){scanf("%d%d%d",&u,&v,&w);if(u<l) l=u;if(v+1>r) r=v+1;Insert(v+1,u,-w);  }for(i=l;i<r;i++){Insert(i+1,i,0);//S[i]-S[i+1]<=0 Insert(i,i+1,1);//S[i+1]-S[i]<=1 }}void SPFA(int s,int e) {int i,u,v;top=0;memset(Instack,false,sizeof(Instack));for(i=s;i<=e;i++)dis[i]=INF;dis[e]=0;//注意要从e开始Stack[++top]=e;Instack[e]=true;while(top){u=Stack[top--];Instack[u]=false;//出栈for(i=head[u];i!=-1;i=E[i].next){v=E[i].to;if(Relax(u,v,E[i].w)&&!Instack[v]){Instack[v]=true;Stack[++top]=v;}}}}int main(){while(scanf("%d",&N)!=EOF){Init();SPFA(l,r);printf("%d\n",-dis[l]); //必有解,无需判负环}return 0;}