1. 程式人生 > >整數區間(poj1716)

整數區間(poj1716)

整數區間(intervals.cpp/pas)

題目描述(Description):
對於一個整數序列,給出它的若干個閉區間[a,b],表示ab包含至少2個不同的
列中,你的任務是找到滿足所有條件的最短的序列的長度。

輸入檔案(dist.in):
第一行一個數n (1 <= n <= 10000),表示有n個區間描述,接下來n行,每行兩個
<= a < b <= 10000)表示區間,

輸出檔案(dist.out):
輸出最短的滿足條件的序列長度。

樣例(Sample):
Sample Input Case 1:
4

6
2 4
0 2
4 7
Sample Output Case 1:
4

/////////////////////////////////////////////////////////////////////////////////////////////////

思路:

對於差分約束的題目,關鍵在於找不等式關係。

從題目條件可以明確的看出以下關係

   s[j] - s[i-1] >= 2  

   s[i] - s[i-1] >= 0

   s[i-1] - s[i] >= -1

所以 就可以用SPFA跑最長路啦!!!

然後就對了啦!!!

/////////////////////////////////////////////////////////////////////////////////////////////////

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<iostream>
using namespace std;
const int inf=0x3f3f3f3f;

int n,maxl=0;
int head[1000000],k=0;
int dis[10000+10];
int inq[10000+10];
int inq_times[10000+10];
queue<int> q;

struct code
{
	int v,w,next;
}e[1000000];

void adde(int u,int v,int w)
{
	e[k].v=v;
	e[k].w=w;
	e[k].next=head[u];
	head[u]=k++;
}

void read()
{
	memset(head,-1,sizeof(head));
	int a,b;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&a,&b);
		adde(a,b+1,2);
		maxl=max(maxl,b+1);
	}
	for(int i=0;i<maxl;i++)
	{
		adde(i,i+1,0);
		adde(i+1,i,-1);
	}
	
}

void work()
{
	memset(dis,-inf,sizeof(dis));
	memset(inq,0,sizeof(inq));
	dis[0]=0;
	inq_times[0]++;
	q.push(0);
	while(!q.empty())
	{
		int u=q.front();q.pop();
		inq[u]=0;
		if(inq_times[u]>maxl)
		{
			dis[maxl]=0;
			break;
		}
		for(int i=head[u];i!=-1;i=e[i].next)
		{
			int v=e[i].v;
			if(dis[v]<dis[u]+e[i].w)
			{
				dis[v]=dis[u]+e[i].w;
				if(!inq[v])
				{
					inq[v]=1;
					q.push(v);
					inq_times[v]++;
				}
			}
		}
	}
	printf("%d\n",dis[maxl]);
}

int main()
{
	read();
	work();
	return 0;
}