Graph 如何将图形中的区域转换为图形(节点和边)结构
我正在解决Graph 如何将图形中的区域转换为图形(节点和边)结构,graph,graph-algorithm,breadth-first-search,Graph,Graph Algorithm,Breadth First Search,我正在解决ioi2007-FLOOD中提出的一个问题,该问题也出现在SPOJ上 我想了很多办法。后来我才知道- Step 0: Converting a region into a node and Step 1: Connecting two nodes with edges only if corresponding regions share at least a segment. Step 2: And then running a BFS on this will simpli
ioi2007-FLOOD
中提出的一个问题,该问题也出现在SPOJ
上
我想了很多办法。后来我才知道-
Step 0: Converting a region into a node and
Step 1: Connecting two nodes with edges only if corresponding regions share at least a segment.
Step 2: And then running a BFS on this will simplify the problem.
我仍然不能考虑端到端的解决方案,但是我想让我们尝试第0步和第1步。
我也失败了。如果前面有一个图像,我可以很容易地看到区域,但不能通过编程
The input would be end co-ordinate points of segments.
我附上一张图片供参考。
解决这个问题当然有很多不同的方法。一种可能的方法是使用计算机领域的技术。以下两个概念尤其有用:
- (DCEL):这种数据结构通常用于处理平面图。基本思想是扩展每条边,以保留对边旁边的区域(也称为“面”)的引用 实现这一点的一种方法是将每个无向边拆分为两个有向边,每个方向一个。然后,可以扩展每个定向边,以保留对其右侧区域的一个引用(从定向边的起始顶点的角度)。此外,扩展每条边以存储对反向边(有时称为“对等”或“双”边)的引用也很有帮助
- :这种类型的算法在处理平面结构时广泛使用。从概念上讲,它通过在平面上移动“扫描线”来工作,同时保持一些中间结果。每次扫描线击中平面上的对象时,中间结果都会基于该对象进行更新。扫描最终对象后,最终结果应可从中间结果派生 在更实际的情况下,这通常是通过按输入点的坐标(即首先按y坐标,如果两个点具有相同的y坐标,则按其x坐标)对输入点进行排序来实现的。然后通过在排序点上迭代来完成“扫描”
使用v_索引t=uint32;
使用e_索引t=uint32;
使用f_索引_t=uint32_t;
constexpr e_index_t NULL_EDGE=0;
constexpr f_index_t外平面=0;
每个顶点存储其位置以及与顶点相关的边。
由于输入图形的边是轴对齐的,因此每个顶点最多可以有四条边。出于这个原因,我使用一个固定大小的数组,四个方向各有四个元素。如果顶点在某个方向上没有边,则使用特殊索引NULL\u边
struct顶点{
int x;
int-y;
阵列事件;
};
边缘按照DCEL方法存储。每条边都是定向的,并包含对其右侧面的引用和对其对等边的引用:
struct-Edge{
v_指数a;
v_指数b;
e_index_t peer;
f_索引面右;
};
每个面都包含包含该面的边列表:
结构面{
向量边;
};
完整图形包含顶点、边和面的列表:
结构图{
向量顶点;
向量边;
向量面;
};
算法
构建输入图形后,构建面的基本方法是:
- 按顶点的坐标对顶点进行排序
- 初始化一个,它最初将每个顶点指定给它自己的分区。分区用于指示哪些顶点可以彼此接触
- 迭代排序的顶点。对于每个顶点,检查从该顶点开始的边的方向。对于每个向左或向下的边,检查当前顶点和该边的端点是否在同一分区中(使用union find数据结构的查找操作)
- 如果是,则边闭合一个内部循环(因为顶点位于同一分区中,如果它们可以彼此接触)。创建一个新的面。从当前边开始,通过始终采用最右侧的后续边,跟随包围面的边。对于每个访问的边,将右转面的DCEL参照设定为指向新创建的面
- 如果否,请在union find数据结构中连接两个分区,以指示两个顶点可以彼此到达(因此,已知可以从其中一个顶点到达的每个顶点也可以从另一个顶点到达)
getsorteddverties
,一个实现联合查找数据结构的辅助类VertexPartition
,以及一个辅助函数applyFaceRightwards
,该函数通过始终取最右边的后继边沿包围面的边移动,识别人脸的主要程序如下所示:
void图形::createFaceGraph(){
//按坐标对顶点排序
自动索引{getsorteddverties()};
//使用每个顶点的一个分区初始化union find数据结构。
VertexPartition分区(顶点.size());
//扫掠已排序的顶点
用于(v_索引\u t当前:索引){