Intervals POJ - 1201 (差分约束)

You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn.
Write a program that:
reads the number of intervals, their end points and integers c1, ..., cn from the standard input,
computes the minimal size of a set Z of integers which has at least ci common elements with interval [ai, bi], for each i=1,2,...,n,
writes the answer to the standard output.

Input

The first line of the input contains an integer n (1 <= n <= 50000) -- the number of intervals. The following n lines describe the intervals. The (i+1)-th line of the input contains three integers ai, bi and ci separated by single spaces and such that 0 <= ai <= bi <= 50000 and 1 <= ci <= bi - ai+1.

Output

The output contains exactly one integer equal to the minimal size of set Z sharing at least ci elements with interval [ai, bi], for each i=1,2,...,n.

Sample Input

5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1

Sample Output

6

题意:一共n个区间,要求找一个集合x,至少含有每个区间[  li  ,  ri ] 元素个数为wi

求集合x的含有最少元素的个数

思路:设dis [ x ]  为区间 [0,x )含有的元素个数

对于每个区间 [ u , v ] 至少有w个元素

则有关系  dis [ v + 1 ] - dis [ u ] >=w;

------------>  dis [ v + 1 ] >= dis[  u ] + w;

可以建一条从 u  到 v+1 权值为 w 的边

对于每个dis [i] 有 dis [ i ] - dis [ i - 1 ] >=0  且 dis [ i ] - dis [ i - 1 ] <= 1

---------------------> dis [ i ]   >=  dis [ i - 1 ] 0  且  dis [ i - 1 ] >=  dis[ i ]   -  1

                             可以建一条从 i-1  到 i 权值为 0 的边

                             可以建一条从 i  到  i - 1   权值为 - 1的边

最后跑一下,最长路

代码:

#include<cstdio>
#include<cstring>
#include<queue>
#define Inf 0x3f3f3f3f
using namespace std;
const int N =  50005;
struct node{
	int v,w;
	int next;
}edge[N*10];
int head[N],id;
int dis[N],vis[N],n;
void init(){
	id=0;
	memset(head,-1,sizeof(head));
}
void add(int u,int v,int w){
	edge[id].v=v;
	edge[id].w=w;
	edge[id].next=head[u];
	head[u]=id++;
}
void SPFA(int s,int t){
	memset(dis,-Inf,sizeof(dis));
	memset(vis,0,sizeof(vis));
	queue<int>p;
	p.push(s);
	dis[s]=0;
	vis[s]=1;
	while(!p.empty()){
		int u=p.front();
		p.pop();
		vis[u]=0;
		for(int i=head[u];i!=-1;i=edge[i].next){
			int v=edge[i].v;
			int w=edge[i].w;
			if(dis[v]<dis[u]+w){
				dis[v]=dis[u]+w;
				if(!vis[v]){
					p.push(v);
				    vis[v]=1;
				}
			}
		}
	}
	printf("%d\n",dis[t]);
}
int main(){
	while(~scanf("%d",&n)){
		init();
		int l=Inf,r=-Inf;
		for(int i=0;i<n;i++){
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			add(u,v+1,w);
			l=min(l,u);
			r=max(r,v+1);
		}
		for(int i=l;i<=r;i++){
			add(i,i-1,-1);
			add(i-1,i,0);
		}
		SPFA(l,r);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/islittlehappy/article/details/81154893
今日推荐