如何找到彼此朋友的大小 k(或更多)的序列?
How to find a sequence of size k(or more) of people that are friends with each other?
我正在尝试解决我国一所大学的考试中提出的问题。它给了我一个文件作为输入,该文件在第一行包含 3 个数字:
。在第二行是关系(形式为(a,b(的m对数字表示a是B的朋友,B是A的朋友(。
任务是找到具有最大长度(至少是k人(的序列,其中人们尽可能有效地彼此成为朋友。如果没有这样的序列,将打印"NO"。
他们的例子:
数据.txt:
5 5 3
1 2 5 1 3 2 4 5 1 4
输出:
1 4 5
数据.txt:
5 5 4
1 2 5 1 3 2 4 5 1 4
输出:
No
数据.txt:
11 18 3
1 8 4 7 7 10 11 10 2 1 2 3 8 9 8 3 9 3 9 2 5 6 5 11 1 4 10 6 7 6 2 8 11 7 11 6
输出.txt:
2 3 6 7 8 9 10 11
我的方法
在这种情况下,友谊可以用无向图表示(至少对我来说,这似乎是最合乎逻辑的数据结构(,其中顶点代表人,边代表友谊。要成为序列的一部分,顶点的度数需要大于或等于 k - 1。
这就是我停下来的地方。目前我所能做的就是消除度数不至少为 k - 1 的节点:
#include <iostream>
#include <fstream>
#include <vector>
#include <utility>
#include <algorithm>
std::ifstream f{ "data.txt" };
constexpr size_t LIMIT = 101;
// graph[i][j]: i is friend with j
// short to avoid vector<bool> specialization
std::vector<std::vector<short>> graph(LIMIT, std::vector<short>(LIMIT, 0));
std::vector<int> validNodes;
int numOfNodes, numOfRelationships, sequenceSize;
void Read()
{
f >> numOfNodes >> numOfRelationships >> sequenceSize;
int a;
int b;
for(int i = 1; i <= numOfRelationships; ++i) {
f >> a >> b;
graph[a][b] = graph[b][a] = 1;
}
}
int Degree(int node)
{
int result = 0;
for(int i = 1; i <= numOfNodes; ++i) {
if(i != node && graph[node][i] == 1) {
++result;
}
}
return result;
}
void KeepValidNodes()
{
for(int i = 1; i <= numOfNodes; ++i) {
if(Degree(i) < sequenceSize - 1) {
// Don't add the node to validNodes vector
// "Remove it from the graph" aka it's not friend with anyone
// all nodes that were friends with it now have a lower degree, remove them from the validNodes vector if that's the case
for(int j = 1; j <= numOfNodes; ++j) {
auto findPos = std::find(validNodes.begin(), validNodes.end(), j);
if(findPos != validNodes.end() && Degree(j) - 1 < sequenceSize - 1) {
*findPos = -1;
}
graph[i][j] = graph[j][i] = 0;
}
}
else {
validNodes.push_back(i);
}
}
}
void PrintSequence()
{
bool empty = true;
for(const int& node : validNodes) {
if(node != -1) {
empty = false;
std::cout << node << std::endl;
}
}
if(empty) {
std::cout << "No" << std::endl;
}
}
int main()
{
Read();
KeepValidNodes();
PrintSequence();
}
这仅适用于他们的前 2 个示例。我能想到的唯一可能的解决方案是生成所有可能的节点组合,看看哪一个满足要求。正如他们所说,我如何有效地解决这个问题?
编辑:
我不一定在寻找一个完全有效的代码,但我什至不知道我该如何解决这个问题。
您的问题是找到大小为 k 或更小的集团。我不知道是否有任何算法能够做到这一点,但肯定有算法能够找到最大规模的集团。一旦你在图中找到最大大小的集团(我们称之为n-集团(,找到大小为<= n的集团就等于从n-集团中提取顶点的子集。
一般情况下没有多项式时间算法,因为这个问题是NP完全的,所以不要指望会有很棒的结果。这个答案包含一个简短的算法列表,这些算法将比蛮力算法更快地解决这个问题。如果你想更多地了解它,你也应该看看 Karp 关于问题可约性的论文(即使你没有将这个概念应用于这个问题,也值得一读,因为NP完全问题的许多解决方案都依赖于约简(。
相关文章:
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 为什么野牛仍在使用"int yylex(void)",却找不到"int yylex(YYS
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到
- 如何找出GDB的SIGTRAP核心转储的根本原因
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 函数何时会在c++中包含stack_Unwind_Resume调用
- 找不到QtResource文件中的文件
- Python中的for循环与C++有何不同
- VC++本机单元测试,找不到调试符号
- RegGetValue在当前用户下找不到名称
- 带有 -stdlib=libc++ 的 clang++ 9.0.1 找不到<optional>
- c++找不到具有相同哈希的无序集合元素
- 一位朋友将模板函数缩写为clang和gcc
- 找不到以下加速库:boost_fiber
- 找不到 FLTK(缺少:FLTK_INCLUDE_DIR)
- 设置 Visual Studio for MPI: 找不到标识符错误
- "assimp/config.h"找不到,但它在文件夹中
- 链接器找不到在虚拟类 c++ 中访问的静态字段的符号
- 从安卓NDK15切换到17使得malloc和朋友找不到