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;
}