题意:
给出N个整数区间[ai,bi],使得序列在区间[ai,bj]的个数>=2个,求出序列的最小长度.此题和1201题类似,不过1201题用Bellman_Ford算法求解会超时,可用SPFA算法求解.
分析:
对于给定的条件,令t[i]表示i是否在区间中,则t[i]可以取0或1.
假设d[i]为序列在[0,i)上的包含的元素个数,即d[i]=t[0]+t[1]+……+d[i-1],则我们可以根据条件得到d[bi+1]-d[ai]>=2,而且我们在根据隐含的条件1>=d[j+1]-d[j]>= 0,可以得到一个差分约束系统,由于此处是求最小值,故用Bellman_Ford算法求约束图的最长路径.
在差分约束系统中如果题目要求是求最小值,就将约束条件转化为">="形式,然后用Bellman_Ford算法求解约束图的最长路径,如果题目要求的是最大值,就将约束条件转化为"<="形式,然后用Bellman_Ford算法求解约束图的最短路径.
CODE:
/*差分约束(求最小值---求最长路径(>=))*/ /*AC代码:32ms*/ #include <iostream> #define MAXN 10005 #define INF 0x7fffffff using namespace std; struct edge { int v,w,next; }E[3*MAXN]; int head[MAXN],ecnt; int Stack[MAXN],dis[MAXN]; bool Instack[MAXN]; int N,top,ll,rr; //d[v]>=d[u]+w(u,v); void Insert(int u,int v,int w) { E[ecnt].v=v; E[ecnt].w=w; E[ecnt].next=head[u]; head[u]=ecnt++; } void Init() { int i,u,v; ll=INF;rr=-INF; memset(head,-1,sizeof(head));ecnt=0; for(i=1;i<=N;i++) { scanf("%d%d",&u,&v); if(u<ll) ll=u; if(v+1>rr) rr=v+1;//注意此处比较操作 Insert(u,v+1,2); } for(i=ll;i<rr;i++) { Insert(i,i+1,0); Insert(i+1,i,-1); } } void SPFA() { int i,u,v,w; memset(Instack,false,sizeof(Instack)); for(i=ll;i<=rr;i++) dis[i]=-INF; top=0; Stack[top++]=ll; Instack[ll]=true; dis[ll]=0; while(top) { u=Stack[--top]; Instack[u]=false; for(i=head[u];i!=-1;i=E[i].next) { v=E[i].v;w=E[i].w; if(dis[v]<dis[u]+w)//最长路 { dis[v]=dis[u]+w; if(!Instack[v]) { Instack[v]=true; Stack[top++]=v; } } } } printf("%d\n",dis[rr]); } int main() { while(scanf("%d",&N)!=EOF) { Init(); SPFA(); } return 0; }