暑假考试题7:clique(线段覆盖+贪心)

题目:

 分析:

对于一个点i来说,它能与j连边仅当两个点的距离>=权值之和,画图抽象出来就是这样:

 将每一点都抽象成一个线段,那么不相交的线段间一定会有连边,问题就转化成了->求最多的线段覆盖。

线段覆盖求法: 贪心。将线段按右端点排序,从左往右依次选取。

正确性:每次选右端点尽量靠左的,后面的选择余地就越多。

扫描二维码关注公众号,回复: 7129761 查看本文章

注意:当右端点相同的时候,要按左端点从小到大排序,因为如果出现左右端点相同的线段,要接着与它右端点相同的点选。

#include<bits/stdc++.h>
using namespace std;
#define N 200005
struct node{
    int l,r;
}e[N];
bool cmp(const node &a,const node &b)
{
    if(a.r==b.r) return a.l<b.l;//如果有空节点 要优先选非空区间 然后后面接一个空区间 这要为答案贡献 1 
    return a.r<b.r;
}
int main()
{
    freopen("clique.in","r",stdin);
    freopen("clique.out","w",stdout);
    int n,a,b;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&a,&b),e[i].l=a-b,e[i].r=a+b;
    sort(e+1,e+1+n,cmp);
    int mx=e[1].r,ans=1;
    for(int i=2;i<=n;i++){
        if(e[i].l>=mx) mx=e[i].r,ans++;
    }
    printf("%d\n",ans);
    return 0;
}
/*
4
2 3
3 1
6 1
0 0

6
1 3
5 1
7 1
10 0
12 1
13 6
*/

猜你喜欢

转载自www.cnblogs.com/mowanying/p/11431449.html