拓扑排序主要是为解决一个工程能否顺序进行的问题,但有时我们还需要解决工程完成需要的最短时间问题。
我们把路径上各个活动所持续的时间之和称为路径长度,从源点到汇点具有最大长度的路径叫关键路径,在关键
路径上的活动叫关键活动。
关键路径算法基于拓扑排序算法,这里直接上代码,以后有机会再详解。
class EdgeNode
{
public $adjvex;
public $weight;
public $next;
public function __construct($adjvex, $weight = 0, $next = null)
{
$this->adjvex = $adjvex;
$this->next = $next;
$this->weight = $weight;
}
}
class VertexNode
{
public $in;
public $data;
public $firstedge = null;
public function __construct($in, $data, $firstedge)
{
$this->in = $in;
$this->data = $data;
$this->firstedge = $firstedge;
}
}
class Graph
{
public $adjList;
public $num;
public function __construct($adjList, $num)
{
$this->adjList = $adjList;
$this->num = $num;
}
}
$EdgeNode0 = new EdgeNode(2, 4, new EdgeNode(1, 3));
$EdgeNode1 = new EdgeNode(4, 6, new EdgeNode(3, 5));
$EdgeNode2 = new EdgeNode(5, 7, new EdgeNode(3, 8));
$EdgeNode3 = new EdgeNode(4, 3);
$EdgeNode4 = new EdgeNode(7, 4, new EdgeNode(6, 9));
$EdgeNode5 = new EdgeNode(7, 6);
$EdgeNode6 = new EdgeNode(9, 2);
$EdgeNode7 = new EdgeNode(8, 5);
$EdgeNode8 = new EdgeNode(9, 3);
$EdgeNode9 = null;
$adjList = array(
new VertexNode(0, 'V0', $EdgeNode0),
new VertexNode(1, 'V1', $EdgeNode1),
new VertexNode(1, 'V2', $EdgeNode2),
new VertexNode(2, 'V3', $EdgeNode3),
new VertexNode(2, 'V4', $EdgeNode4),
new VertexNode(1, 'V5', $EdgeNode5),
new VertexNode(1, 'V6', $EdgeNode6),
new VertexNode(2, 'V7', $EdgeNode7),
new VertexNode(1, 'V8', $EdgeNode8),
new VertexNode(2, 'V9', $EdgeNode9),
);
$graph = new Graph($adjList, 10);
//----------------------- 第一种 ------------------------------------
$etv = array_fill(0, 10, 0);
$stackTop = $stackTop2 = -1;
$count = 0;
$stack = $stack2 = array();
foreach ($graph->adjList as $adjKey => $adjItem) {
if ($adjItem->in == 0) {
$stack[++$stackTop] = $adjKey;
}
}
while ($stackTop != -1) {
$getTop = $stack[$stackTop--];
// printf("%s -> ", $graph->adjList[$getTop]->data);
$count += 1;
$stack2[++$stackTop2] = $getTop;
for ($e = $graph->adjList[$getTop]->firstedge; !empty($e); $e = $e->next) {
$k = $e->adjvex;
$graph->adjList[$k]->in -= 1;
if (!$graph->adjList[$k]->in) {
$stack[++$stackTop] = $k;
}
if (($etv[$getTop] + $e->weight) > $etv[$k]) {
$etv[$k] = $etv[$getTop] + $e->weight;
}
}
}
//关键路径
$ltv = array_fill(0, $graph->num, $etv[$graph->num - 1]);
while ($stackTop2 != 0) {
$getTop = $stack2[$stackTop2--];
for ($e = $graph->adjList[$getTop]->firstedge; !empty($e); $e = $e->next)
{
$k = $e->adjvex;
if (($ltv[$k] - $e->weight) < $ltv[$getTop] ) {
$ltv[$getTop] = $ltv[$k] - $e->weight;
}
}
}
for ($j = 0; $j < $graph->num; $j++) {
for ($e = $graph->adjList[$j]->firstedge; !empty($e); $e = $e->next)
{
$k = $e->adjvex;
$ete = $etv[$j];
$lte = $ltv[$k] - $e->weight;
if ($ete == $lte) {
echo "<" . $graph->adjList[$j]->data . "," . $graph->adjList[$k]->data . "> length: " . $e->weight . " , ";
}
}
}
if ($count < $graph->num) {
exit('不是AOV网');
} else {
exit('是的');
}