clique 解题报告
Posted ppprseter
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了clique 解题报告相关的知识,希望对你有一定的参考价值。
clique
题目描述
数轴上有 (n) 个点,第 (i) 个点的坐标为 (x_i),权值为 (w_i)。两个点 (i),(j) 之间存在一条边当且仅当 (abs(x_i-x_j)>=w_i+w_j)。你需要求出这张图的最大团的点数。(团就是两两之间有边的顶点集合)
输入数据
第一行一个整数 (n),接下来 (n) 行每行两个整数 (x_i,w_i)。
输出数据
一行一个整数表示答案
数据范围
对于 (20\%) 的数据, (n<=10)。
对于 (60\%) 的数据, (n<=1000)。
对于 (100\%) 的数据, (n<=200000), (0<=|x_i|,w_i<=10^9)。
考试的时候发现了一个性质
如果三个点按从左到右排,点1点2有边且点2点3右边可以得到点1点3有边
于是可以(N^2)连边跑topo最长路(从左到右连有向边)
想拿(set)优化连边但是没想到。
结果数组开小爆30了。
正解算是没想到吧。
如果把点看做形如([x-w,x+w])的区间,那么两个点有连边等价于区间无交点。
于是问题转化成了不重合的区间数量
可以简单的贪心,也可以DP
复杂度都是(O(nlogn))的
Code:
#include <cstdio>
#include <algorithm>
const int N=2e5+10;
struct node
{
int l,r;
bool friend operator <(node n1,node n2){return n1.r<n2.r;}
}seg[N];
int rr[N],dp[N],f[N],pos[N],n;
int max(int x,int y){return x>y?x:y;}
int main()
{
scanf("%d",&n);
for(int x,w,i=1;i<=n;i++)
{
scanf("%d%d",&x,&w);
seg[i].l=x-w,seg[i].r=x+w;
rr[i]=seg[i].r;
}
std::sort(seg+1,seg+1+n);
std::sort(rr+1,rr+1+n);
rr[0]=seg[1].r-1;
for(int i=1;i<=n;i++)
{
int l=0,r=i-1;
while(l<r)
{
int mid=l+r+1>>1;
if(seg[i].l>=rr[mid])
l=mid;
else
r=mid-1;
}
pos[i]=l;
}
for(int i=1;i<=n;i++)
dp[i]=f[pos[i]]+1,f[i]=max(f[i-1],dp[i]);
printf("%d
",f[n]);
return 0;
}
2018.10.13
以上是关于clique 解题报告的主要内容,如果未能解决你的问题,请参考以下文章