Integer Intervals POJ - 1716(贪心 or 差分约束)

An integer interval [a,b], a < b, is a set of all consecutive integers beginning with a and ending with b.
Write a program that: finds the minimal number of elements in a set containing at least two different integers from each interval.

Input

The first line of the input contains the number of intervals n, 1 <= n <= 10000. Each of the following n lines contains two integers a, b separated by a single space, 0 <= a < b <= 10000. They are the beginning and the end of an interval.

Output

Output the minimal number of elements in a set containing at least two different integers from each interval.

Sample Input

4
3 6
2 4
0 2
4 7

Sample Output

4

题意:

一共给n个区间,找一个集合,使得该集合在每个区间的元素恰好为2个,求该集合包含元素

最少的个数

思路一:

将每个区间按右端点从小到大排序,从0到n遍历每个区间,贪心计算集合的个数

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 10005;
struct node{
	int s,e;
	bool operator<(const node p){
		return e<p.e;
	}
}arr[N];
int main(){
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%d%d",&arr[i].s,&arr[i].e);
	}
	sort(arr,arr+n);
	//fi为区间的倒数第二个数
	//se为区间的最后一个数 
	int fi=arr[0].e-1,se=arr[0].e;
	int ans=2;
	for(int i=1;i<n;i++){
		if(arr[i].s<=fi) continue; //说明fi,se在区间arr[i]中 
		else if(arr[i].s<=se){//fi在区间arr[i]中,se不在 
			fi=se;
			se=arr[i].e;
			ans++;
		}
		else if(arr[i].s>se){ //fi,se均不在区间内 
			fi=arr[i].e-1;
			se=arr[i].e;
			ans+=2;
		}
	}
	printf("%d\n",ans);
	return 0;
}

思路二:

差分约束,列出有关系不等式,转化为求最小路

设dis[ x ] 为x到0所包含的元素个数(不包含x)

有题意可得  dis [ v+1 ]  -  dis [u] >= 2      v点在u点之后

                    dis[u]  <=  dis [v+1]  -  2

                   建一条从v+1到u权值为 -2 的路径

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

                               建一条从i+1到 i  权值为 0 的路径

                               建一条从 i 到 i+1 权值为 1 的路径

求所有点到0 的最短路 

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

猜你喜欢

转载自blog.csdn.net/islittlehappy/article/details/81152266