残差图最快的数据结构
Fastest data structure for residual graphs
本文关键字:数据结构 更新时间:2023-10-16
我正在尝试实现具有数千个节点和边的流算法,因此我需要有效的数据结构。目前我做的是:
结构节点:
Double Linked Array (Parents) //Edges that enter the node (basicaly a tuple that contains a pointer to the parent node and the weight, current flow of the edge
Double Linked Array (Sons) //Edges that leave the node
问题是,当我执行BFS时,给定一个节点v,我需要查看残差图中的边(基本上是你发送流的边的反向边),剩下v。因为我可以有平行的边,我需要始终知道哪个后边来自哪个前边。
目前,我解决这个问题的方法是首先处理子节点(v)中的所有边,然后定义一个映射,给出所有这些边在目标节点w中的父节点(w)的索引。因此,我得到了我存储的倒边,并可以执行我的算法。然而,这些地图的访问时间是log(E),这大大降低了我的算法速度。我应该如何处理这个问题(双链表被实现为std::vector)?
int src,snk,nnode,nedge;
int fin[100000],dist[100000];//nodes
int cap[100000],next[100000],to[100000];
void init(int s,int sn,int n)
{
src=s,snk=sn,nnode=n,nedge=0;
memset(fin,-1,sizeof(fin));
}
void add(int u,int v,int c)
{
to[nedge]=v,cap[nedge]=c,next[nedge]=fin[u],fin[u]=nedge++;
to[nedge]=u,cap[nedge]=0,next[nedge]=fin[v],fin[v]=nedge++;
}
bool bfs()
{
int e,u,v;
memset(dist,-1,sizeof(dist));
dist[src]=0;
queue<int> q;
q.push(src);
while(!q.empty())
{
u=q.front();
q.pop();
for(e=fin[u];e>=0;e=next[e])
{
v=to[e];
if(cap[e]>0&&dist[v]==-1)
{
dist[v]=dist[u]+1;
q.push(v);
}
}
}
if(dist[snk]==-1)
return false;
else
return true;
}
int dfs(int u,int flow)
{
if(u==snk)
return flow;
int e,v,df;
for(e=fin[u];e>=0;e=next[e])
{
v=to[e];
if(cap[e]>0&&dist[v]==dist[u]+1)
{
df=dfs(v,min(cap[e],flow));
if(df>0)
{
cap[e]-=df;
cap[e^1]+=df;
return df;
}
}
}
return 0;
}
int dinitz()
{
int ans=0;
int df,i;
while(bfs())
{
while(1)
{
df=dfs(src,INT_MAX);
if(df>0)
ans+=df;
else
break;
}
}
return ans;
}
这是我的迪尼茨算法代码这里init函数初始化邻接表Add在列表中添加一条新边,fin给出邻接列表中的最后一个节点因此u可以通过以下循环
访问列表中的所有元素for(e=fin[u];e>=0;e=next[e])
{
v=to[e];
}
,其中u是u要查找的相邻元素所在的节点V会给出u的邻元素此外,当找到最大流量时,你需要前边缘和后边缘假设前缘是e那么后沿将是e^1反之亦然,但为此,边的起始索引应该是0
我使用的表示类似于边缘列表,但带有附加信息
typedef long long dintype;
struct edge{
edge(int t_ = 0,int n_ = 0, dintype c_ = 0){
to = t_;
next = n_;
cap = c_;
}
int to,next;
dintype cap;
};
const int max_edges = 131010;
const int max_nodes = 16010;
edge e[max_edges];
int first[max_nodes]; // initialize this array with -1
int edges_num;
inline void add_edge(int from,int to, dintype cap){
if(edges_num == 0){
memset(first,-1,sizeof(first));
}
e[edges_num].to = to;e[edges_num].cap = cap;
e[edges_num].next = first[from];first[from] = edges_num++;
e[edges_num].to = from;e[edges_num].cap = 0;
e[edges_num].next = first[to];first[to] = edges_num++;
}
我使用全局数组是为了更好地解释这个概念。我将此用于我的dinitz算法。
现在解释一下。在数组"e"我抓住了所有的边。在数组first[v]中,我保存数组e中v的第一个边的索引。如果在数组e的索引idx中存在一条边,则反向边存储在索引idx^1的元素中。因此,这种表示使我们能够拥有一个邻居列表(从第一个[v]开始,并遵循下一个索引直到它变为-1),并且能够在常数时间内访问反向边。
相关文章:
- 链表,反向函数,数据结构
- 如何使用set实现无序数据结构?
- 我们可以将数据永久保存为数据结构吗?
- C++中的可变长度数组/数据结构
- 用于存储由空格分隔的字符串的 C++/C 数据结构
- 通过 NIF 从C++返回自定义数据结构
- 编译器上的策略数据结构不起作用
- 尝试构建"lock-free"数据结构C++
- 设计将引用元素移动到开头的数据结构.C++
- 在学习数据结构之前对STL有一个了解是好的吗?
- 如何解析表示树状数据结构的字符串
- 我对数据结构、双向链表有一些问题
- googletest:测试太大的数据结构
- C++中deque数据结构的大O是什么?
- 我可以使用哪种数据结构来处理这种方式
- 将文本文件解析为树状数据结构
- C++ 中具有 O(1) 搜索时间复杂度的数据结构
- 哪些存储了不完整类型的 STL 数据结构可以用作类成员?
- C++,您能否设计一种数据结构,将指针保存在连续内存中并且不会使它们失效?
- 带参数的数据结构的全局声明