有向无环图的快速生成算法
Fast algorithm for generating Directed Acyclic Graph
本文关键字:算法 更新时间:2023-10-16
我有个问题,非常感谢您的帮助。我必须生成一个有2^N个节点的DAG它们的值从0到2^(N-1)节点x和y之间存在有向边(x和y是它们的值),如果x <Y和非负整数p,如x⊕Y>
#include <iostream>
#include <vector>
#include <math.h>
typedef unsigned int unint;
using namespace std;
class Node
{
friend class DAG;
private:
unint value;
vector<Node* > neighbourTo;
vector<Node* > neighbors;
public:
Node(unint );
};
Node::Node(unint _value)
: value(_value) {}
class DAG
{
private:
int noNodes;
vector<Node* > nodes;
public:
DAG(int );
void initializeNodes(int ,int );
int isPowerOf2(unsigned int );
int getMaxNaighbourTo(int );
int getMinNeighbor(int );
int numberOfPathsLengthK(int );
int recursion(Node& , int );
void print();
};
DAG::DAG(int size)
{
noNodes = size;
nodes.resize(noNodes);
int i, j;
initializeNodes(0, noNodes-1);
for(i = 0; i < noNodes-1; i++)
{
for(j = i+1; j < noNodes; j++)
{
if(isPowerOf2(i ^ j))
{
nodes[i]->neighbors.push_back(nodes[j]);
nodes[j]->neighbourTo.push_back(nodes[i]);
}
}
}
}
void DAG::initializeNodes(int min, int max)
{
if(max == min)
nodes[max] = new Node(max);
else
{
int s = (max + min)/2;
initializeNodes(min, s);
initializeNodes(s+1, max);
}
}
int DAG::isPowerOf2(unsigned int value)
{
return ((value != 0) && !(value & (value - 1)));
}
int DAG::getMaxNaighbourTo(int index)
{
if(index > 0 && index <= (noNodes-1))
{
int size = nodes[index]->neighbourTo.size();
return nodes[index]->neighbourTo[size-1]->value;
}
return -1;
}
int DAG::getMinNeighbor(int index)
{
if(index >= 0 && index < (noNodes-1))
return nodes[index]->neighbors[0]->value;
return -1;
}
int DAG::numberOfPathsLengthK(int K)
{
if(K <= 0)
return 0;
long int paths = 0;
for(int i = 0; i < nodes.size(); i++)
{
paths += recursion(*nodes[i], K - 1);
}
return (paths % 100003);
}
int DAG::recursion(Node& node, int K)
{
if( K <= 0 )
return node.neighbors.size();
else
{
long int paths = 0;
for(int i = 0; i < node.neighbors.size(); i++)
{
paths += recursion(*node.neighbors[i], K - 1);
}
return paths;
}
}
void DAG::print()
{
for(int i = 0; i < nodes.size(); i++)
{
cout << "Node: " << nodes[i]->value << "tNeighbors: ";
for(int j = 0; j < nodes[i]->neighbors.size(); j++)
{
cout << nodes[i]->neighbors[j]->value << " ";
}
cout << endl;
}
}
int main()
{
int
N, M, K,
i, j;
cin >> N >> M >> K;
DAG graf(pow(2, N));
graf.print();
cout << "==1==" << endl;
cout << graf.getMaxNaighbourTo(M) << endl;
cout << "==2==" << endl;
cout << graf.getMinNeighbor(M) << endl;
cout << "==3==" << endl;
cout << graf.numberOfPathsLengthK(K) << endl;
return 0;
}
下面是一个简单的输出:
4 3 2
Node: 0 Neighbors: 1 2 4 8
Node: 1 Neighbors: 3 5 9
Node: 2 Neighbors: 3 6 10
Node: 3 Neighbors: 7 11
Node: 4 Neighbors: 5 6 12
Node: 5 Neighbors: 7 13
Node: 6 Neighbors: 7 14
Node: 7 Neighbors: 15
Node: 8 Neighbors: 9 10 12
Node: 9 Neighbors: 11 13
Node: 10 Neighbors: 11 14
Node: 11 Neighbors: 15
Node: 12 Neighbors: 13 14
Node: 13 Neighbors: 15
Node: 14 Neighbors: 15
Node: 15 Neighbors:
2
7
48
nodes是Node指针的向量,Node a是保存节点值和两个向量的类,一个是指向当前节点邻居的Node指针,另一个是指向当前节点邻居节点的Node指针。以上代码是用c++编写的。我为任何语法错误道歉。英语不是我的母语。
第一个明显的非算法性能增益将是而不是来构建图,如果您只需要打印邻居,则无需创建数据结构即可这样做。这里的第二个改进是避免用每个输出行刷新流…
对于算法改进,给定一个数字N=0011010
(例如,任何数字都是有效的),你需要找出哪个数字满足两个要求,N xor M
是2的幂,N > M
。第一个要求意味着这两个数字在一个位上完全不同,第二个要求意味着这个位必须在M
中被点燃而不是在N
中被点燃,所以只看上面的位的答案将是:M = { 1011010, 0111010, 0011110, 0011011 }
。现在你可以通过扫描N
中的每个位来获得所有这些,如果是0
,那么设置它并打印值。
// assert that 'bits < CHAR_BITS * sizeof(unsigned)'
const unsigned int max = 1u << bits;
for (unsigned int n = 1; n < max; ++n) {
std::cout << "Node: " << n << " Neighbors: ";
for (unsigned int bit = 0; i < bits; ++i) {
unsigned int mask = 1 << bit;
if (!(n & mask)) {
std::cout << (n | mask);
}
}
std::cout << 'n';
}
对于给定节点的最小和最大邻居,您可以应用相同的推理,给定数字N的最大可达邻居将是M,使得N中最高的0位被点亮。对于最小可达邻居,您需要M,使得最低的0位被设置为1。
我有一些空闲时间写了一个草图,看看:
struct node
{
std::vector<std::shared_ptr<node> > link;
};
int main()
{
int N = 4;
int M = 1<<N;
std::vector<std::shared_ptr<node> > tree(M, std::make_shared<node>());
for(int i=0;i<M;++i)
{
std::cout<<"node: "<<i<<" is connected to:n";
for(int p=0;p<N;++p)
{
int j= (1<<p) ^ i; //this is the evaluation you asked for
//it's the inverse of i ^ j = 2^p
if(j<=i) continue;
tree[i]->link.push_back(tree[j]);
std::cout<<j<<" ";
}
std::cout<<std::endl;
}
}
演示对于N=4
,即2^4=16
节点,程序打印
node: 0 is connected to:
1 2 4 8
node: 1 is connected to:
3 5 9
node: 2 is connected to:
3 6 10
node: 3 is connected to:
7 11
node: 4 is connected to:
5 6 12
node: 5 is connected to:
7 13
node: 6 is connected to:
7 14
node: 7 is connected to:
15
node: 8 is connected to:
9 10 12
node: 9 is connected to:
11 13
node: 10 is connected to:
11 14
node: 11 is connected to:
15
node: 12 is connected to:
13 14
node: 13 is connected to:
15
node: 14 is connected to:
15
node: 15 is connected to:
我希望这就是你要找的。获得乐趣。
相关文章:
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 基于ELO的团队匹配算法
- C++选择排序算法中的逻辑错误
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- C++A*算法并不总是在路径中具有目标节点
- 排序算法c++
- 构建可组合有向图(扫描仪生成器的汤普森构造算法)
- 算法问题:查找从堆栈中弹出的所有序列
- 下面是排序算法O(n)吗
- KMP算法和LPS表构造的运行时间
- 为什么我的排序算法会更改数组值
- 求最大元素位置的分治算法
- 具有非整数边容量的最大流量的Dinic算法
- 到连接组件算法的问题(递归)
- STL算法函数在多个一维容器上的使用
- 读取最后一行代码算法 - c++ 时出现问题
- 括号更改 O(n) 算法
- std::unordered_map 搜索算法是如何实现的?
- 如何实现高效的算法来计算大型数据集的多个不同值?
- 如何在 Mac 上使用 c++17 并行标准库算法?