您的位置:首页 > 产品设计 > UI/UE

分析公式 Codeforces 528B Clique Problem

2015-08-25 15:06 375 查看
http://codeforces.com/contest/528/problem/b

Clique Problem

time limit per test
2 seconds

memory limit per test
256 megabytes

input
standard input

output
standard output

The clique problem is one of the most well-known NP-complete problems. Under some simplification it can be formulated as follows. Consider an undirected graph G.
It is required to find a subset of vertices C of the maximum size such that any two of them are connected by an edge in graph G.
Sounds simple, doesn't it? Nobody yet knows an algorithm that finds a solution to this problem in polynomial time of the size of the graph. However, as with many other NP-complete problems, the clique problem is easier if you consider a specific type of a
graph.

Consider n distinct points on a line. Let the i-th
point have the coordinate xi and
weight wi.
Let's form graph G, whose vertices are these points and edges connect exactly the pairs of points (i, j),
such that the distance between them is not less than the sum of their weights, or more formally: |xi - xj| ≥ wi + wj.

Find the size of the maximum clique in such graph.

Input

The first line contains the integer n (1 ≤ n ≤ 200 000)
— the number of points.

Each of the next n lines contains two numbers xi, wi (0 ≤ xi ≤ 109, 1 ≤ wi ≤ 109)
— the coordinate and the weight of a point. All xi are
different.

Output

Print a single number — the number of vertexes in the maximum clique of the given graph.

Sample test(s)

input
4
2 3
3 1
6 1
0 2


output
3


Note

If you happen to know how to solve this problem without using the specific properties of the graph formulated in the problem statement, then you are able to get a prize of one million dollars!

The picture for the sample test.



直接分析公式啊啊啊啊啊!!!

题意:

给定数轴上的n个点。

下面n行每行两个数 xi, wi 表示点和点权。

对于任意两个点u, v

若dis(u,v) >= u_w+v_w 则这两个点间可以建一条边。(in other words 若两点间距离大于两点的权值和则可以建边)

找一个最大团,输出这个最大团的点数。

#include <bits/stdc++.h>
#define ll int
using namespace std;
pair<ll,ll>p[200005];
int main()
{
	ll n,i,w,x,s=0,l=-(1<<31);
	cin>>n;
	for(i=0;i<n;i++)
		cin>>x>>w,p[i]=make_pair(x+w,x-w);
	sort(p,p+n);
	for(i=0;i<n;i++)
		if(p[i].second>=l)
			l=p[i].first,s++;
	cout<<s;
}


顺便提一下用DP,线段树或树状数组的同学!

其实对于一个权值点我们可以认为是一个区间

如: 4 5 ,可以认为是区间[-1, 9]

则这个点可以从区间(-inf, 1]转移过来,即val(9) = max(val(9), 区间(-inf, -1]最大值+1)

然后前面区间最值就用树状数组或者线段树维护
#include <stdio.h>  
#include <string.h>  
#include <iostream>  
#include <math.h>  
#include <queue>  
#include <set>  
#include <vector>
#include <string>
#include <algorithm>  
template <class T>
inline bool rd(T &ret) {
    char c; int sgn;
    if (c = getchar(), c == EOF) return 0;
    while (c != '-' && (c<'0' || c>'9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}
template <class T>
inline void pt(T x) {
    if (x <0) {
        putchar('-');
        x = -x;
    }
    if (x>9) pt(x / 10);
    putchar(x % 10 + '0');
}
using namespace std;
const int N = 400010;
#define L(x) tree[x].l
#define R(x) tree[x].r
#define Max(x) tree[x].max
#define Lson(x) (x<<1)
#define Rson(x) (x<<1|1)
#define Lazy(x) tree[x].lazy
struct Node{
    int l, r, max, lazy;
}tree[N<<2];
void Down(int id){
    Max(Lson(id)) = max(Lazy(id), Max(Lson(id)));
    Max(Rson(id)) = max(Lazy(id), Max(Rson(id)));
    Lazy(Lson(id)) = max(Lazy(id), Lazy(Lson(id)));
    Lazy(Rson(id)) = max(Lazy(id), Lazy(Rson(id)));
}
void U(int id){
    Max(id) = max(Max(Lson(id)), Max(Rson(id)));
}
void build(int l, int r, int id){
    L(id) = l; R(id) = r;
    Max(id) = Lazy(id) = 0;
    if (l == r)return;
    int mid = (l + r) >> 1;
    build(l, mid, Lson(id)); build(mid + 1, r, Rson(id));
}
int query(int l, int r, int id){
    if (l == L(id) && R(id) == r)return Max(id);
    Down(id);
    int mid = (L(id) + R(id)) >> 1, ans ;
    if (r <= mid)
        ans = query(l, r, Lson(id));
    else if (mid < l)
        ans = query(l, r, Rson(id));
    else ans = max(query(l, mid, Lson(id)), query(mid + 1, r, Rson(id)));
    U(id);
    return ans;
}
void up(int l, int r, int val, int id){
    if (l == L(id) && R(id) == r){
        Max(id) = max(Max(id), val);
        Lazy(id) = max(Lazy(id), val);
        return;
    }
    Down(id);
    int mid = (L(id) + R(id)) >> 1;
    if (r <= mid)
        up(l, r, val, Lson(id));
    else if (mid < l)
        up(l, r, val, Rson(id));
    else {
        up(l, mid, val, Lson(id));
        up(mid + 1, r, val, Rson(id));
    }
    U(id);
}
vector<int>G;
int hehehe;
struct Edge{
    int l, r;
}x
;
bool cmp(Edge a, Edge b){
    return a.r < b.r;
}
int n, m;
int a
, b
;
int main(){
    while (~scanf("%d", &n)){
        G.clear();
        for (int i = 1; i <= n; i++){
            rd(a[i]); rd(b[i]);
            x[i].l = a[i] - b[i];
            x[i].r = a[i] + b[i];
            G.push_back(x[i].l);
            G.push_back(x[i].r);
        }
        sort(G.begin(), G.end());
        G.erase(unique(G.begin(), G.end()), G.end());
        for (int i = 1; i <= n; i++){
            x[i].l = lower_bound(G.begin(), G.end(), x[i].l) - G.begin() + 1;
            x[i].r = lower_bound(G.begin(), G.end(), x[i].r) - G.begin() + 1;
        }
        sort(x + 1, x + n + 1, cmp);
        build(1, G.size(), 1);
        int ans = 1;
        for (int i = 1; i <= n; i++){
            int tmp = query(1, x[i].l, 1) + 1;
            ans = max(ans, tmp);
            up(x[i].r, x[i].r, tmp, 1);
        }
        pt(ans); puts("");
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: