题目大意:
给出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 0x7fffffff
using 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]<=-w
for(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;
}