我对图论非常陌生,并且很难解决这个问题。给定一个简单的表(单向),如何使用select语句找到定义的起点和终点的最长路径?
似乎需要一些递归语句,但我无法理解它。如果有人可以提供帮助,那就太棒了。
我正在使用Postgresql。
+ -------- + ------ + -------- +
| fromnode | tonode | distance |
+ -------- + ------ + -------- +
| 1 | 2 | 1306 |
| 1 | 6 | 2661 |
| 2 | 3 | 919 |
| 2 | 4 | 629 |
| 3 | 4 | 435 |
| 3 | 5 | 1225 |
| 3 | 7 | 1983 |
| 5 | 6 | 1483 |
| 5 | 7 | 1258 |
+ -------- + ------ + -------- +
答案 0 :(得分:2)
您可以使用此递归CTE,例如:
with recursive params as (
select 1 fromnode,
7 tonode
),
paths as (
select ARRAY[fromnode] pathnodes,
fromnode lastnode,
0 sumdistance
from params
union all
select pathnodes || e.tonode,
e.tonode,
sumdistance + e.distance
from paths
join edges e on e.fromnode = lastnode
cross join params p
where e.fromnode <> p.tonode
and e.tonode <> all(pathnodes)
)
select pathnodes, sumdistance
from paths, params
where lastnode = tonode
order by sumdistance desc
limit 1
(此处和那里可能需要 ,具体取决于列的类型。)
http://rextester.com/VRFHK43986
然而,这将始终计算每个可能的路径(从params.fromnode
开始;没有圆圈)&amp;之后会选择最长的。
修改:上面的解决方案假定图表是定向的。如果它是无向的,您可以对其进行修改,以便使用从tonode
到fromnode
的边缘:
with recursive params as (
select 7 fromnode,
1 tonode
),
paths as (
select ARRAY[fromnode] pathnodes,
fromnode lastnode,
0 sumdistance
from params
union all
select pathnodes || e.nodeb,
e.nodeb,
sumdistance + e.distance
from paths
cross join lateral (select fromnode nodea,
tonode nodeb,
distance
from edges
where fromnode = lastnode
union
select tonode nodea,
fromnode nodeb,
distance
from edges
where tonode = lastnode) e
cross join params p
where e.nodea <> p.tonode
and e.nodeb <> all(pathnodes)
)
select pathnodes, sumdistance
from paths, params
where lastnode = tonode
order by sumdistance desc
limit 1;
但是,(LEAST(fromnode, tonode), GREATEST(fromnode, tonode))
可能需要一个唯一索引,以避免重复,row1.fromnode = row2.tonode and row1.tonode = row2.fromnode
。 (查询不处理这种类型的重复,并且在这种情况下将使用2个单独的路径进行计算。)