POJ 1201 Intervals 差分约束

http://poj.org/problem?id=1201

题目大意:

有一个序列,题目用n个整数组合 [ai,bi,ci]来描述它,[ai,bi,ci]表示在该序列中处于[ai,bi]这个区间的整数至少有ci个。如果存在这样的序列,请求出满足题目要求的最短的序列长度是多少。

思路:

设s[i]为从1~i的整数个数。

这样对于区间[ a , b]显然有 S[b] - S[a-1] >=c[i] (为什么是a-1?因为闭区间a也要选上呀)

然后还有

0<= S[B]-S[B-1] <=1 (整数的话最多比前一个大一,好吧,我大二- -|||我不二啊!!)

变形得:

S[B]-S[B-1] >=0

S[B-1]-S[B]>=-1

然后图就可以建立出来啦~~~~

老样子,我也加了一个点连接到所有的点(为什么?见我上一篇http://blog.csdn.net/murmured/article/details/18780557)




#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=50000+10;
const int MAXM=500000;
const int INF=-100000000;
struct edge
{
	int to;
	int val;
	int next;
}e[MAXM];

int head[MAXN],len,n,m,c,start,dis[MAXN];
void add(int from,int to,int val)
{
	e[len].to=to;
	e[len].val=val;
	e[len].next=head[from];
	head[from]=len++;
}

bool vis[MAXN];
void spfa()
{
	for(int i=start;i<=n;i++)
	{
			dis[i]=INF;
			vis[i]=0;
	}
	queue<int> q;
	dis[0]=0;
	vis[0]=true;
	q.push(0);

	while(!q.empty())
	{
		int cur=q.front();
		q.pop();
		vis[cur]=false;

		for(int i=head[cur];i!=-1;i=e[i].next)
		{
			int id=e[i].to;
			if(dis[cur] + e[i].val > dis[id])
			{
				dis[id]=dis[cur]+e[i].val;
				if(!vis[id])
				{
					vis[id]=true;
					q.push(id);
				}
			}
		}
	}
}


int main()
{
	while(~scanf("%d",&m))
	{
		len=0;
		memset(head,-1,sizeof(head));
		n=0;
		start=9999999;
		for(int i=1;i<=m;i++)
		{
			int from,to,val;
			scanf("%d%d%d",&from,&to,&val);
			add(from-1,to,val);
			if(to >n)		n=to;
			if(start > from)  start=from;
		}

		for(int i=start;i<=n;i++)
		{
			add(0,i,0);
			add(i,i-1,-1);
			add(i-1,i,0);
		}
		spfa();
		printf("%d\n",dis[n]);

	}

	return 0;
}





POJ 1201 Intervals 差分约束

上一篇:poj - 2777 - Count Color(线段树)


下一篇:端口检测工具Fport的使用