c++ - 枚举唯一的无向路径的有效方法

标签 c++ algorithm boost graph

给定节点{1,2,...,N}的子集,是否有任何STLboost函数在所有节点上返回唯一的无向旅程?std::next_permutation()给出所有N!指导的游览,其中1-2-...-NN-N-1-...-2-1不同。
但是,在这种情况下,我不希望它们两者都只需要其中之一。本质上,我只想列举旅行团的N! / 2
以下使用std::next_permutation()unordered_set的代码有效,但是还有效率更高的方法吗?以下代码从本质上生成了所有N!指示的巡视,并在检查了unordered_set()之后丢弃了其中的一半。

#include <vector>
#include <unordered_set>
#include <algorithm>
#include <boost/functional/hash.hpp>

template <typename T, typename U> bool unorderedset_val_there_already_add_if_not(std::unordered_set<T, U>& uos, T& val) {
    if (uos.find(val) != uos.end())
        return true;//val already there
    uos.insert(val);
    return false;//Value is new.
}

int main() {
    std::vector<int> sequence{ 1, 2, 3};
    std::unordered_set<std::vector<int>, boost::hash<std::vector<int>>> uos;

    do {
        printf("Considering ");
        for (std::size_t i = 0; i < sequence.size(); i++)
            printf("%d ", sequence[i]);
        printf("\n");
        std::vector<int> rev_sequence = sequence;
        std::reverse(rev_sequence.begin(), rev_sequence.end());
        if (unorderedset_val_there_already_add_if_not(uos, sequence) || unorderedset_val_there_already_add_if_not(uos, rev_sequence)) {
            printf("Already there by itself or its reverse.\n");
        }
        else {
            printf("Sequence and its reverse are new.\n");
        }
    } while (std::next_permutation(sequence.begin(), sequence.end()));
    getchar();
}
也就是说,给定{1,2,3},我只想枚举(1-2-3)(1-3-2)(2-1-3)。其他三个排列(2-3-1)(3-1-2)(3-2-1)不应枚举,因为它们的反向顺序已经被枚举。

最佳答案

如果您想保留next_permutation而不是使用自己的生成器例程,最简单的方法是在某些条件下过滤掉一半排列。
很简单:最后一个元素应该大于第一个元素。

#include <vector>
#include <algorithm>
#include "stdio.h"

int main() {
    std::vector<int> sequence{ 1, 2, 3, 4};
    
    do {
        if (sequence[sequence.size()-1] > sequence[0]) {
            for (std::size_t i = 0; i < sequence.size(); i++)
                printf("%d ", sequence[i]);
            printf("\n");
        }        
    } while (std::next_permutation(sequence.begin(), sequence.end()));
    getchar();
}

1 2 3 4 
1 2 4 3 
1 3 2 4 
1 3 4 2 
1 4 2 3 
1 4 3 2 
2 1 3 4 
2 1 4 3 
2 3 1 4 
2 4 1 3 
3 1 2 4 
3 2 1 4 
可能自己的实现:
Generate all pairs (start; end)     where start < end  
  Generate all permutations of `n-2` values without start and end  
      For every permutation make {start, permutation.., end}

1 ... 2 + permutations of {3, 4}
1 3 4 2
1 4 3 2  
1 ... 3 + permutations of {2,4}
1 2 4 3
1 4 2 3  
...
3 ... 4 + permutations of {1, 2}
3 1 2 4
3 2 1 4  
...

关于c++ - 枚举唯一的无向路径的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63445072/

相关文章:

c++ - 使用 asio null_buffers boost asio udp 套接字

c++ - 获取流程描述

c++ - if block 的同步,C++

c++ - Boost::Regex 段错误(我认为)

python - Pisarze - 波兰信息学奥林匹克竞赛的数据分析任务

algorithm - 按比例平衡 3 个值

c++ - 正确使用 C++ 'for each' 选项

c++ - 抽象类和 move 语义

java - 像Java一样在类内部定义C++方法

algorithm - 为什么我们应该使用带内存的动态规划来解决 - 最小硬币数来找零