C - Clique Problem

针对特定类型的图,解决最大团问题。通过构造有向图,使用贪心算法找到最多节点数的最大团。输入为一系列带有权重的点,输出为最大团的大小。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C - Clique Problem
题目重述:
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.
Examples
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.
在这里插入图片描述题目网址:https://vjudge.net/contest/404852#problem/C

大概意思是:假设点Xi>Xj,那么绝对值符号可以去掉,即Xi-Xj≥Wi+Wj。移项可以得到Xi-Wi≥Xj+Wj。这样的话,其实就确定了一个有向图的关系。

思路:将题目转化为找结点数最多的有向图。运用贪心的思想,肯定希望第一个结点的坐标尽量小,以便于容纳更多的结点。因此事先计算出P(X+W,X-W)后放入vector,排序后从第一个点开始尝试,只要满足这样的关系式就努力往后拓展。这样得到的有向图结点数一定是最多的。

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define N 200006
int n;
struct Node{
   int x,w;
}node[N];
struct Node1{
   int num1,num2;
};
vector<Node1> G;
bool cmp(Node1 a,Node1 b){
   if(a.num1!=b.num1) return a.num1<b.num1;
   return a.num2<b.num2;
}
int main()
{
   while(scanf("%d",&n)==1){
       for(int i=0;i<n;i++){
           scanf("%d%d",&node[i].x,&node[i].w);
       }
	   G.clear();
       for(int i=0;i<n;i++){
           int num1=node[i].x+node[i].w;
           int num2=node[i].x-node[i].w;
           Node1 tmp;
           tmp.num1=num1;
           tmp.num2=num2;
           G.push_back(tmp);
       }
       sort(G.begin(),G.end(),cmp);
       int ans=1;
       Node1 tmp=G[0];
       for(int i=1;i<G.size();i++){
           if(tmp.num1<=G[i].num2){
              ans++;
              tmp=G[i];
           }
       }
       printf("%d\n",ans);
   }
    return 0;
}
### k-clique 的概念及其在社交网络中的应用 在一个无向图 \( G=(V,E) \) 中,如果存在一个子图使得其中任意两个不同的顶点都由一条边直接相连,则此子图称为完全图或者团 (clique)[^1]。当这个完全图恰好有 \( k \) 个节点时,就称之为 \( k \)-clique 或者 \( k \)-团。 对于社交网络而言,\( k \)-clique 可以用来表示一组高度互联的朋友群组,在这样的群组里每个人都是其他人的朋友或者是彼此间的关系非常密切。寻找这些紧密联系的小团体有助于深入理解社会关系网内部结构特征,并可用于多种实际应用场景之中,比如推荐新朋友、预测信息扩散路径等。 #### 寻找最大 \( k \)-clique 的基本思路 为了有效地找出所有的 \( k \)-cliques,可以采用递归的方式遍历整个图形: - **初始化阶段**:设定初始参数,包括待探索的最小团大小 \( k_{min} \),以及当前正在考察的最大已知团尺寸 \( max\_size \)。 - **剪枝操作**:利用一些先验条件提前终止不必要的搜索分支,减少计算量。例如,若某节点剩余邻居数目不足以构成新的更大团,则可以直接跳过对该节点进一步深挖的可能性。 - **回溯过程**:从单个起点出发逐步扩大候选集合直到满足预设阈值为止;一旦发现符合条件的新团即记录下来并尝试继续延伸至更高阶数;如果不成功则返回至上一状态重新选取不同方向前进。 具体到实现层面,KClist++ 提出了基于 Frank-Wolfe 算法框架来优化这一流程,它能够动态调整各定点的重要性评分从而指导后续的选择决策,不过其缺点在于每次迭代都要重做一次完整的枚举工作,导致整体耗时较长[^3]。 另一方面,针对传统方法中存在的效率瓶颈问题——特别是那些依赖于频繁执行最大流运算或是反复求解所有可能存在的 \( k \)-Clique 的方案——研究者们也在不断探索更加高效的替代途径,旨在降低算法复杂度的同时提升处理速度和适用范围[^4]。 ```python def find_k_cliques(graph, k): cliques = [] def extend_candidates(current_set, candidates): nonlocal graph if len(current_set) >= k: is_complete = all((u,v) in graph.edges or (v,u) in graph.edges for u in current_set for v in current_set if u != v) if is_complete and sorted(list(current_set)) not in map(sorted, cliques): cliques.append(set(current_set)) elif candidates: candidate_node = next(iter(candidates)) neighbors_of_candidate = set([n for n in graph.neighbors(candidate_node)]) new_candidates_with_node = candidates.intersection(neighbors_of_candidate) extend_candidates(current_set | {candidate_node}, new_candidates_with_node) new_candidates_without_node = candidates.difference({candidate_node}) extend_candidates(current_set, new_candidates_without_node) nodes = list(graph.nodes()) while nodes: node_to_start = nodes.pop() initial_neighbors = set(graph.neighbors(node_to_start)) extend_candidates({node_to_start}, initial_neighbors) return cliques ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值