POJ 1201 Intervals

POJ_1201

第一次接触差分约束系统的题目,有点摸不着头脑,看了别人的解析后又觉得差分约束系统也好神奇呵!假以时日,我一定会掌握它!

我们设S[i]为区间[0,i)之内的Z元素的数量,那么根据输入可以构成一个约束条件S[b+1]-S[a]>=c,另外还有两个隐含条件,S[i+1]-S[i]>=0S[i+1]-S[i]<=1,实际上还有另外一个条件S[b+1]-S[a]<=b+1-a,但这个条件可以由S[i+1]-S[i]<=1推导出来,所以就不必管它了。

然后把上面3个条件变形后得到S[b+1]+(-c)>=S[a]S[i]+0<=S[i+1]S[i]+1>=S[i+1],然后根据这3个条件建图,之后令S[max(b)+1]=0,求到S[min(a)]的最短路即可,最后结果就是S[max(b)+1]-S[min(a)]

     另外这个题目边比较多,一开始用普通队列开小了RE,所以干脆换成了循环队列,但换成循环队列的时候一定要记得把while(front<rear)这个条件换成while(front!=rear)

#include<stdio.h>
#include
<string.h>
int first[50010],next[150010],v[150010],w[150010];
int q[150010],d[50010],inq[50010];
int main()
{
int i,j,k,n,front,rear,max,min,a,b,c,e,u;
while(scanf("%d",&n)==1)
{
max
=0;
min
=1000000;
memset(first,
-1,sizeof(first));
for(e=0;e<n;e++)
{
scanf(
"%d%d%d",&a,&b,&c);
b
++;
if(b>max)
max
=b;
if(a<min)
min
=a;
w[e]
=-c;
v[e]
=a;
next[e]
=first[b];
first[b]
=e;
}
for(i=min+1;i<=max;i++)
{
w[e]
=0;
v[e]
=i-1;
next[e]
=first[i];
first[i]
=e;
e
++;
}
for(i=min;i<max;i++)
{
d[i]
=1000000;
inq[i]
=0;
w[e]
=1;
v[e]
=i+1;
next[e]
=first[i];
first[i]
=e;
e
++;
}
d[max]
=0;
front
=rear=0;
q[rear
++]=max;
while(front!=rear)
{
u
=q[front++];
if(front>max)
front
=0;
inq[u]
=0;
for(e=first[u];e!=-1;e=next[e])
if(d[u]+w[e]<d[v[e]])
{
d[v[e]]
=d[u]+w[e];
if(!inq[v[e]])
{
q[rear
++]=v[e];
if(rear>max)
rear
=0;
inq[v[e]]
=1;
}
}
}
printf(
"%d\n",d[max]-d[min]);
}
return 0;
}

  

原文地址:https://www.cnblogs.com/staginner/p/2138094.html