hdoj 1384 Intervals

Intervals

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3332    Accepted Submission(s): 1227


Problem Description
You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn.

Write a program that:

> reads the number of intervals, their endpoints 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 <= 50 000) - 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 <= 50 000 and 1 <= ci <= bi - ai + 1.

Process to the end of file.

 
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个区间的左右端点,和这个区间内至少存在的在集合s中的点的个数,让你求集合s中最少有多少个点
题解:重在找到差分约束的约束条件,将约束条件转化为xj-xi<=k的形式,然后建立一条从i到j权值为k的边;
设maxl为区间的左端点,maxr为区间的右端点,S[i] 表示集合Z里面的元素在区间[0, i ]的个数,Maxl,Maxr分别表示所有区间里面的最左端和最右端,dist[]数组存储源点到某点的最短路。则由题意得限制条件
一 S[right] -  S[left-1] >= least 即[left, right]区间个数不小于least,转换得S[left-1] - S[right] <= least;
二 0 <= S[i] - S[i-1] <= 1转换得 S[i-1] - S[i] <= 0 && S[i] - S[i-1] <= 1。
第二个条件题中并没有给出,需要自己推导,因为仅仅靠题中的条件无法构建一个连通图,也就无法求最短路,因为s[i]表示的是集合Z里面的元素在区间[0, i ]的个数所以s[i]至多比s[i-1]大一也可能相等
然后根据限制条件建图
转化问题:题目需要求的是S[Maxr] - S[Maxl-1] >= ans 即S[Maxl-1] - S[Maxr] <= -ans。 若以Maxr为源点 ,而-ans就为Maxr到Maxl-1的最短路径的相反数,即-dist[Maxl-1]。
 
#include<stdio.h>
#include<string.h>
#include<queue>
#define INF 0x3f3f3f
#define MAX 200000
#include<algorithm>
using namespace std;
int n,ans;
int maxl,maxr;
int vis[MAX],dis[MAX];
int head[MAX];
struct node
{
	int u,v,w;
	int next;
}edge[MAX];
void add(int u,int v,int w)
{
	edge[ans].u=u;
	edge[ans].v=v;
	edge[ans].w=w;
	edge[ans].next=head[u];
	head[u]=ans++;
}
void init()
{
	ans=0;
	maxl=INF;
	maxr=0;
	memset(head,-1,sizeof(head));
}
void getmap()
{
	int i,j,a,b,c;
	while(n--)
	{
		scanf("%d%d%d",&a,&b,&c);
		maxl=min(maxl,a);
		maxr=max(maxr,b);
		add(b,a-1,-c);
	}
	for(i=maxl;i<=maxr;i++)
	{
		add(i,i-1,0);
		add(i-1,i,1);
	}
}
void spfa()
{
	int i,j;
	queue<int>q;
	memset(vis,0,sizeof(vis));
	for(i=maxl-1;i<=maxr;i++)//以maxr为源点,也可以以maxl为源点,不过要对建图稍作修改 
	    dis[i]=INF;
	dis[maxr]=0;
	vis[maxr]=1;
	q.push(maxr);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(i=head[u];i!=-1;i=edge[i].next)
		{
			int top=edge[i].v;
			if(dis[top]>dis[u]+edge[i].w)
			{
				dis[top]=dis[u]+edge[i].w;
				if(!vis[top])
				{
					vis[top]=1;
					q.push(top);
				}
			}
		}
	}
	printf("%d
",-dis[maxl-1]);
}
int main()
{
	while(scanf("%d",&n)!=EOF)
	{
		init();
		getmap();
		spfa();
	}
	return 0;
}

  

 
 
原文地址:https://www.cnblogs.com/tonghao/p/4743583.html