数据结构——图

数据结构笔记目录:

1. 绪论、时间复杂度
2. 线性表
3. 树
4. 图
5. 查找
6. 排序


4.1 基本概念

不存在空图

  • 顶点集一定非空

  • 边集可以为空

图和树是逻辑上的区别,都是 逻辑结构

4.1.1 顶点的度

{ 无向图 ∑ i = 1 n T D ( v i ) = 2 e 有向图 ∑ i = 1 n T D ( v i ) = ∑ i = 1 n I D ( v i ) + ∑ i = 1 n O D ( v i ) ∑ i = 1 n I D ( v i ) = ∑ i = 1 n O D ( v i ) = e \begin{cases} 无向图\\ &\sum_{i=1}^nTD(v_i)=2e \\ 有向图\\ &\sum_{i=1}^nTD(v_i)=\sum_{i=1}^nID(v_i)+\sum_{i=1}^nOD(v_i)\\ &\sum_{i=1}^{n}ID(v_i)=\sum_{i=1}^nOD(v_i)=e \end{cases} 无向图有向图i=1nTD(vi)=2ei=1nTD(vi)=i=1nID(vi)+i=1nOD(vi)i=1nID(vi)=i=1nOD(vi)=e

4.1.2 图的种类

1. 简单图
  • v i → v j v_i \rightarrow v_j vivj 间无重复边
  • 任一顶点无自身到自身的顶点
2. n个顶点的完全图

{ 无向图 n ( n − 1 ) 2 条边 有向图 n ( n − 1 ) 条边 \begin{cases} 无向图\\ &\frac{n(n-1)}{2}条边 \\ 有向图\\ &n(n-1)条边 \end{cases} 无向图有向图2n(n1)条边n(n1)条边

3. 子图

顶点集为图G的子集

  • 并非所有的顶点子集与边子集的组合都是图G的子图
  • 任一条边及其两个端点都在的边集与顶点集的组合才构成子图
4. 连通图[无向图]

无向图连通:顶点 v → w v\rightarrow w vw 直接有路径

图 G 中任两顶点间都连通

  • 一点可以访问全部
  • 若边数小于n-1,则一定是非连通图
  1. 连通分量:无向图中极大连通子图
  2. 生成树:连通图 的包含所有结点的极小连通子图
    • 包含n-1条边,n个顶点
    • 加一条边构成回路,减一条边为非连通图
  3. 生成森林:非连通图 的多个连通分量生成的多个树构成的森林
5. 路径&完全图
路径

v p → v q v_p \rightarrow v_q vpvq 之间的顶点序列

  • 路径长度:路径中的顶点个数
  • 距离: v p → v q v_p \rightarrow v_q vpvq 的最短路径长度
  • 简单路径:顶点不重复

回路、环:起点和终点 ( v p = = v q v_p == v_q vp==vq) 相同的路径

  • 简单回路:除首尾顶点不重复的路径
  • 有拓扑序列的图一定无环
完全图

已知有n个顶点,确保连通的的最小边数为:n-1个顶点的完全图的边数+1, ( n − 1 ) ( n − 2 ) 2 + 1 \frac{(n-1)(n-2)}{2}+1 2(n1)(n2)+1

已知有n条边,组成非连通图的顶点数为:k个顶点组成完全图+1, k ( k − 1 ) 2 + 1 ⇒ ⌈ 2 n ⌉ + 1 \frac{k(k-1)}{2}+1\Rightarrow \lceil \sqrt{2n} \rceil+1 2k(k1)+12n +1

6. 强连通图[有向图]

有向图连通: v ⇄ w v\rightleftarrows w vw ,双向连通

每对顶点间有 路径

  • 不是每对顶点间都有
  1. 强连通分量

    有向图中的极大强连通图

  2. 有向完全图一定是强连通图

4.2 图的存储

4.2.1 邻接矩阵法

1. 规则
  1. 表示

{ 无权图 取 0 或 1 带权图 w i j 或 0 或 ∞ \begin{cases} 无权图 &取0或1 \\ 带权图 &w_{ij}或0或\infty \end{cases} {无权图带权图01wij0

  1. 无向图

    • 邻接矩阵对称且唯一

    • 可进行压缩存储,只存放上(下)三角矩阵元素

      对称矩阵默认为无向图

    • 第i行(列)非零元素个数= v i v_i vi 的出度OD( v i v_i vi )或者入度ID( v i v_i vi )

  2. 有向图

    • 第i行非零且非 ∞ \infty 的元素个数为顶点 v i v_i vi 的出度
    • 第i列非零且非 ∞ \infty 的元素个数为顶点 v i v_i vi 的入度
2. 特点
  1. 适用于 稠密图 存储

  2. 空间复杂度为 O ( ∣ v ∣ 2 ) O(\mid v\mid^2) O(v2)

  3. 确定两点之间是否有边 O ( 1 ) O(1) O(1) ——数组的随机存取特性

    确定图中边数 O ( ∣ v ∣ 2 ) O(\mid v\mid^2) O(v2)

  4. 某个顶点出度越大,则存储矩阵的行非零元素越多

  5. 图G的邻接矩阵为A,则 A n [ i ] [ j ] A^n[i][j] An[i][j] 表示从 v i → v j v_i \rightarrow v_j vivj 的长度为n的路径数量

3. 表示
typedef struct{
    VexType Vex[MaxVertexNum];//顶点集
    EdgeType Edge[MaxVertexNum][MaxVertexNum];//邻接矩阵表示边集
    int vexnum,arcnum;
}MGraph;
4. 有向无环图的矩阵表示

有向无环图:非零元素集中在上三角或下三角区域,其对称区域全为0

  • 图中比不存在环
  • 一定存在拓扑序列但不唯一

上三角:出度大编号小

下三角:入度大编号小

4.2.2 邻接表法

邻接表法:只存出度

逆邻接表法:只存入度

邻接表:每个顶点 v 建立相应的边表

  • 顶点头指针(顺序存储) :顶点头指针为边链表的头指针,指向与 v i v_i vi 关联的首条边

  • 边信息(单链表)

    无向图:依附于 v i v_i vi 的边

    有向图:以 v i v_i vi 为尾的弧

1. 特点
  1. 适用于 稀疏图

  2. 邻接表 不唯一

    同一顶点的边结点连接顺序不唯一,取决于建立边表的算法及边的输入序列

  3. 存储空间

    无向图: O ( ∣ v ∣ + 2 ∣ e ∣ ) O(\mid v\mid+2\mid e\mid) O(v+2e)

    有向图: O ( ∣ v ∣ + ∣ e ∣ ) O(\mid v\mid+\mid e\mid) O(v+e)

  4. 时间复杂度

    找所有邻边:读顶点的边表—— O ( n ) O(n) O(n)

    确定边是否存在:扫一个端点的边表—— O ( n ) O(n) O(n)

  5. 有向图某顶点的度

    出度:邻接表中结点个数

    入度:需遍历全部邻接表

2. 表示
typedef struct{
    VexType data;
    ArcNode *firstArc;
}VNode,AdList[MaxVertexNum];//邻接表

typedef struct{
    int adjvex;//邻接点域
    double weigh;//边表权值
    struct ArcNode *nextArc;//邻接顶点
}ArcNode;//边表结点

typedef struct{
    int vexnum;
    int arcnum;
    AdList vertices;//顶点头指针
}AGraph;

在这里插入图片描述

4.2.3 邻接多重表

无向图的存储结构

在这里插入图片描述

4.2.4 十字链表法

有向图的存储结构

在这里插入图片描述

4.3 图的基本操作

独立于存储结构

参数相同;实现不同,性能不同

Adjacent(G,x,y);//x与y之间是否存在边
Neighbors(G,x);//x的邻接边
FirstNeighbor(G,x);//G中x的第一个邻接点
NextNerghbor(G,x,y);//G中除x的下一个邻接点

InsertVertex(G,x);//插入点
DeleteVertex(G,x);//删除点

AddEdge(G,x,y);//新增边
RemoveEdge(G,x,y);//移除边

已知n个顶点的图,其邻接矩阵表示为MGraph,邻接表表示为LGraph

  1. 判别图中边数 n(e)

    n(x):表示x的个数

    无向图有向图
    MGraph n ( e ) = n ( 1 ) 2 n(e)=\frac{n(1)}{2} n(e)=2n(1) n ( e ) = n ( 1 ) n(e)=n(1) n(e)=n(1)
    LGraph n ( e ) = n ( e N o d e ) 2 n(e)=\frac{n(eNode)}{2} n(e)=2n(eNode) n ( e N o d e ) n(eNode) n(eNode)
  2. 判断两点是否连通

    MGraph M G r a p h [ i ] [ j ] = ? 1 MGraph[i][j] \overset{?}{=}1 MGraph[i][j]=?1 O ( 1 ) O(1) O(1)
    LGraph遍历顶点i的邻接表 O ( e ) O(e) O(e)
  3. 度的计算

    无向图有向图
    MGraph 2 ∗ 第 i 行 ′ 1 ′ 的个数 2*第 i 行 '1' 的个数 2i1的个数出度:第 i 行 ‘1’ 的个数
    入度:第 i 列 ‘1’ 的个数
    LGraphn(eNode) 出度:表头为 i 的单链表中 e N o d e 的个数 出度:表头为 i 的单链表中 eNode 的个数 出度:表头为i的单链表中eNode的个数
    入度:边表中 i 的个数 入度:边表中 i 的个数 入度:边表中i的个数

4.3 图的遍历

从某一顶点出发,沿图中的边对图中所有顶点访问且只访问一次

  • 遍历与经过的区别

    从某一点出发经过图中所有结点 ≠ \neq = 遍历:每个结点不重复的访问一次

  • 对每个顶点查找邻接点的过程取决于存储结构

    矩阵: O ( ∣ v ∣ 2 ) O(\mid v\mid^2) O(v2)

    邻接表: O ( ∣ e ∣ ) O(\mid e\mid) O(e)

  • 树是一种特殊的图

4.3.1 广度优先搜索

从某一顶点 v 开始,由近到远访问和 v 有路径长度为1,2,3…的顶点

  • 逐层访问,故需要借助队列
1. 实现
bool visted[MAX_VERTEX_NUM];

bool BFSTraverse(Graph G){
    //初始化
    for(int i = 0;i < G.vernum;++i)
        visited[i] = FALSE;
    InitQueue(Q);
    
    //BFS
    for(int i = 0;i < G.vexnum;++i)
        if(!visited[i])
            BFS(G,i);//使用for循环确保每个连通分量都被访问
}

void BFS(Graph G,int v){//从顶点v出发,广度优先遍历图G
	visit(v);
    visited[v] = TRUE;
    EnQueue(Q,v);//顶点v入队
    
    while(!isEmpty(Q)){
        DeQueue(Q,v);
        for(w = FirstNeighbor(G,v);w >= 0;
            				w=NextNeighbor(G,v,w)){
            //检测v的所有邻接点w
            if(!visited[w]){//w为v尚未访问的邻接点
                visit(w);
                visited[w] = TRUE;
                EnQueue(Q,w);
            }
        }
    }
}
2. 性能分析
  1. 空间复杂度

    O ( ∣ v ∣ ) O(\mid v\mid) O(v)

  2. 时间复杂度[与采取的存储方式有关]

    • 邻接矩阵 O ( ∣ v ∣ 2 ) O(\mid v\mid^2) O(v2)

    • 邻接表 O ( ∣ v ∣ + ∣ e ∣ ) O(\mid v\mid+\mid e\mid) O(v+e)

      顶点入队 O ( ∣ v ∣ ) O(\mid v\mid) O(v)

      搜索所有邻接点,访问边 O ( ∣ e ∣ ) O(\mid e\mid) O(e)

3. 应用
  1. u → v u \rightarrow v uv 路径长度最小的路径

  2. 无权图求单源点最短路径

    void BFS_Min_Distance(Graph G,int u){
        //d[i]表示从u到i的最短路径
        for(i = 0;i < G.vexnum;++i)
            d[i] = INFINITE;
        visited[u] = TRUE;
        d[u] = 0;
        EnQueue(Q,u);
        while(!isEmpty(Q)){
            DeQueue(Q,u);//BFS算法主过程
            for(w = FirstNeighbor(G,u);w >= 0;
               			w = NextNeighbor(G,u,w)){
                if(!visited[w]){
    				visited[w] = TRUE;//设已访问标记
                    d[w] = d[u]+1;
                    EnQueue(Q,w);
                }
            }
        }
    }
    
  3. 广度优先生成树

    邻接矩阵:表示法唯一 ⟹ \Longrightarrow 生成树唯一

    邻接表:表示法不唯一 ⟹ \Longrightarrow 生成树不唯一

4.3.2 深度优先搜索

{ 图的邻接矩阵唯一 ⟹ 基于邻接矩阵的 D F S 、 B F S 序列唯一 图的邻接表不唯一 ⟹ 基于邻接表的 D F S 、 B F S 序列不唯一 \begin{cases} & 图的邻接矩阵唯一 \Longrightarrow 基于邻接矩阵的DFS、BFS序列唯一 \\ & 图的邻接表不唯一\Longrightarrow 基于邻接表的DFS、BFS序列不唯一 \end{cases} {图的邻接矩阵唯一基于邻接矩阵的DFSBFS序列唯一图的邻接表不唯一基于邻接表的DFSBFS序列不唯一

DFS——递归算法,用一个递归工作栈,空间复杂度 O ( ∣ v ∣ ) O(\mid v\mid) O(v)

性能分析

  • 时间复杂度

    邻接矩阵 O ( ∣ v ∣ 2 ) O(\mid v\mid^2) O(v2)

    邻接表 O ( ∣ v ∣ + ∣ e ∣ ) O(\mid v\mid+\mid e\mid) O(v+e)

  • 空间复杂度

    O ( ∣ v ∣ ) O(\mid v\mid) O(v)

bool visited[MAX_VERTEX_NUM];//访问标记数组

void DFSTraverse(Graph G){
    for(v = 0;v < G.vexnum;++v) //初始化
        visited[v] = FALSE;
    for(v = 0;v < G.vexnum;++v)//遍历所有连通分量
        if(!visited[v])
            DFS(G,v);
}

void DFS(Graph G,int v){
    visit(v);
    visited[v] = TRUE;//访问v并做标记
    for(w = FirstNeighbor(G,v);w >= 0;
        			w = NextNeighbor(G,v,w)){
        if(!visited[w])
            DFS(G,w);
    }
}

4.3.3 图的遍历与连通性

  1. 连通

    • 无向图:从某一顶点 v 出发,一次遍历可访问图中所有顶点
    • 有向图:初始点到图中每个顶点都有路径
  2. 连通分量个数

  • DFSTraverse / BFSTraverse 中调用 DFS / BFS 次数为连通分量数
  1. 对一个有向无环图,DFSTraverse 的退栈序列就是一个拓扑序列
    在这里插入图片描述

4.4 应用

4.4.1 最小生成树

  1. 边数 = 顶点数 - 1

  2. 带权连通图权值和最小

    最小权值和唯一,但树形不唯一

    若各边权值互不相等,则树形唯一

Generate_MST(Graph G){
    T = NULL;
    while T未形成树
        do 找最小代价边(u,v)且加入T后不形成回路
    		T = T ∪ (u,v);
}
1. 深度优先、广度优先生成树

在这里插入图片描述

2. Prim算法

选点:Prime——Point

手动模拟

在这里插入图片描述

实现

void Prim(G,T){
    T = ∅;//初始化为空集
    U = {'a'};//MST的顶点集
    while((V-U) != ∅){
        设(u,v)是使 u∈U与v∈V,且权值最小的边;
        T = T∪{(u,v)};
        U = U∪{v};
    }
}

时间复杂度: O ( ∣ v ∣ 2 ) O(\mid v\mid^2) O(v2) ,故不依赖于边集,适用于稠密图

3. Kruskal算法

在这里插入图片描述

void Kruskal(G,T){
    T = V;//初始化树,仅含顶点
    numS = n;//连通分量数
    while(numS > 1){//若连通分量数大于1
        从E中取出权值最小的边(v,w);
        if(v和u属于不同连通分量){
            T = T∪{(v,u)};//将此边加入生成树中
            numS--;
        }
    }
}

时间复杂度: O ( ∣ e ∣ l o g ∣ e ∣ ) O(\mid e\mid log\mid e\mid) O(eloge) ,适用于点多边少

4.4.2 最短路径

带权路径长度:路劲上权值的和

  • 满足连通的 u → v u \rightarrow v uv
  • 找所有 u → v u \rightarrow v uv 中权值最小的路径

区别:

Dijkstra : 单源点最短路径

Floyd : 多源点最短路径

1. Dijkstra

在这里插入图片描述

void Dijkstra(MGraph G,int v0,Patharc P,ShortPathTable D){
	int flag[MAXVEX];//访问标记数组 0-未访问 1-已访问 
	for(int i = 0;i < G.numVertices;++i){
		flag[i] = 0;
		D[i] = G.arc[v0][i];//D[]为距离数组 
		P[i] = 0;//P[i]为到达vi的路径长度 
	} 
	D[v0] = 0,flag[v0] = 1,P[0] = 0;
	
	for(int i = 0;i < G.numVertices;++i){
		int min = INFINITY;//记录当前距离最小值 
		int idx;//记录距离最小值下标 
		for(int j = 0;j < G.numVertices;++j)//查找距离v0最近的点 
			if(!flag[j] && D[j] < min){//vj未被访问且距离最小 
				idx = j;
				min = D[j];
			}
		
		flag[idx] = 1;
		for(int w = 0;w < G.numVertices;++w)//更新各顶点最小距离 
			if(!flag[w] && (min + G.arc[idx][w] < D[w]))
				D[w] = min + G.arc[idx][w]; 
		P[i+1] = idx;
	} 
}
2. Floyd

在这里插入图片描述

A ( 0 ) = [ 0 6 13 10 0 4 / 19 5 15 / ∞ 0 ] = [ 0 6 13 10 0 4 5 15 0 ] P A T H ( 0 ) = [ a b a c b a b a c / b c c a c a b / c b ] = [ a b a c b a b c c a c a b ] \begin{gathered} A^{(0)}= \begin{bmatrix} 0 & 6 & 13 \\ 10 & 0 & 4/19 \\ 5 & 15/\infty & 0 \end{bmatrix} =\begin{bmatrix} 0 & 6 & 13 \\ 10 & 0 & 4 \\ 5 & 15 & 0 \end{bmatrix} PATH^{(0)}= \begin{bmatrix} & ab & ac \\ ba & & bac/bc \\ ca & cab/cb & \end{bmatrix} =\begin{bmatrix} & ab & ac \\ ba & & bc \\ ca & cab & \end{bmatrix} \end{gathered} A(0)= 01056015/∞134/190 = 010560151340 PATH(0)= bacaabcab/cbacbac/bc = bacaabcabacbc

A ( 1 ) = [ 0 6 10 / 13 10 0 4 5 / ∞ 15 0 ] = [ 0 6 13 10 0 4 5 15 0 ] P A T H ( 1 ) = [ a b a b c / a c b a b c c b a / c a c a b ] = [ a b a c b a b c c a c a b ] \begin{gathered} A^{(1)}= \begin{bmatrix} 0 & 6 & 10/13 \\ 10 & 0 & 4 \\ 5/\infty & 15 & 0 \end{bmatrix} =\begin{bmatrix} 0 & 6 & 13 \\ 10 & 0 & 4 \\ 5 & 15 & 0 \end{bmatrix} PATH^{(1)}= \begin{bmatrix} & ab & abc/ac \\ ba & & bc \\ cba/ca & cab & \end{bmatrix} =\begin{bmatrix} & ab & ac \\ ba & & bc \\ ca & cab & \end{bmatrix} \end{gathered} A(1)= 0105/∞601510/1340 = 010560151340 PATH(1)= bacba/caabcababc/acbc = bacaabcabacbc

A ( 2 ) = [ 0 ∞ / 6 13 9 / 10 0 4 5 15 0 ] = [ 0 6 13 9 0 4 5 15 0 ] P A T H ( 2 ) = [ a c b / a b a c b c a / b a b c c a c a b ] = [ a b a c b c a b c c a c a b ] \begin{gathered} A^{(2)} =\begin{bmatrix} 0 & \infty/6 & 13 \\ 9/10 & 0 & 4 \\ 5 & 15 & 0 \end{bmatrix} =\begin{bmatrix} 0 & 6 & 13 \\ 9 & 0 & 4 \\ 5 & 15 & 0 \end{bmatrix} PATH^{(2)}= \begin{bmatrix} & acb/ab & ac \\ bca/ba & & bc \\ ca & cab & \end{bmatrix} = \begin{bmatrix} & ab & ac \\ bca & & bc \\ ca & cab & \end{bmatrix} \end{gathered} A(2)= 09/105∞/60151340 = 09560151340 PATH(2)= bca/bacaacb/abcabacbc = bcacaabcabacbc

4.4.3 有向无环图

有向无环图:一个有向图中无环,简称DAG

用于描述公共子式

  • 符号最多为二元运算符
  • 出现多少种运算数就多少个叶结点

在这里插入图片描述

4.4.4 拓扑排序

在一个有向无环图的顶点组成的序列中

  • 每个顶点出现且只出现一次
  • 若顶点A在序列中排在顶点B前面,则在图中不存在B->A的路径

对有向无环图的一种排序,若存在一条顶点A到顶点B的路径,则在排序中顶点B出现在顶点A的后面。

1. AOV

AOV(用顶点表示活动):若用DAG表示一个工程,顶点表示活动,有向边 < v i , v j > <v_i,v_j> <vi,vj> 表示活动 v i v_i vi 必须先于活动 v j v_j vj 发生的关系。

  • v i v_i vi v j v_j vj 的直接前驱, v j v_j vj v i v_i vi 的直接后继,具有传递性
  • 任何活动 v i v_i vi 都不能以自身作为前驱或者后继

在这里插入图片描述

2. 拓扑排序步骤
  1. 每次从AOV中选一个没有前驱(入度=0)的顶点输出

  2. 从AOV网中删除该顶点和以该顶点为起点的所有边

  3. 重复 1. 2. 直至当前的AOV为空或当前网中不存在无前驱的顶点

    若AOV为空,则该图存在拓扑序列

    若AOV不空,则该图不存在拓扑序列

在这里插入图片描述

3. 拓扑排序实现
bool TopologicalSort(Graph G){
    InitStack(S);//初始化栈,存储入度为0的顶点
    for(int i = 0;i < G.vexnum;++i)
        if(indegree[i] == 0)
            Push(S,i);//将所有入度为0的顶点入栈
    
    int count = 0;//表示已经输出的顶点数
    while(!IsEmpty(S)){
        Pop(S,i);//栈顶元素出栈
        print[count++] = i;//输出顶点i
        for(p = G.vertices[i].firstarc;p;p = p->nextarc){
            //将所有i指向的顶点入度减1并将入度为0的顶点压栈
            v = p->adjvex;//v是p的邻接点
            if(!(--indegree[v]))
                Push(S,v);//入度为0则入栈
        }
    }
    if(count < G.vexnum)
        return false;//排序失败,有向图有回路
    else
        return true;//存在拓扑序列
}
  • 时间复杂度: O ( ∣ v ∣ + ∣ e ∣ ) O(\mid v\mid+\mid e\mid) O(v+e)

  • 入度为零的顶点,即没有前驱活动的或前驱活动全部完成的顶点,工程可以从这个顶点所代表的活动开始或继续

  • 若一个顶点有多个直接后继,则拓扑序列不唯一

  • AOV网中各个顶点地位相同,故可重新编号,若是DAG则其邻接矩阵是三角矩阵

4.4.5 关键路径

1. AOE

有向无环图中,顶点表示事件,有向边表示活动,边上权值表示完成该活动的开销。用边表示活动的图为AOE。

  • 只有在顶点所代表的事件发生后,从该顶点出发的有向边代表的活动才能开始
  • 只有在进入某顶点各有向边所代表的活动完成后,该顶点所代表的事件才能发生
  • AOE网中,只有一个入度为0的顶点(源点),表示整个工程开始;一个出度为0的顶点(汇点),表示整个工程结束

在这里插入图片描述

拓扑序列: v 1 , v 2 , v 3 , v 4 , v 5 , v 5 , v 6 , v 7 , v 8 , v 9 v_1,v_2,v_3,v_4,v_5,v_5,v_6,v_7,v_8,v_9 v1,v2,v3,v4,v5,v5,v6,v7,v8,v9

2. 关键路径

从源点到汇点的路径中,具有最大路径长度的路径;关键路径上的活动为关键活动

  • 加快关键活动可以缩短整个工程的工期,但缩短到一定程度,关键活动会为非关键活动
  • 若AOE网中关键路径不唯一,只有加快公共的关键路径上的关键活动,才能缩短工期

在这里插入图片描述

3. 活动的最早开始时间最晚开始时间

活动最早开始时间 = 活动的起点事件最早开始时间

活动的最晚开始时间 = 活动的终点事件最晚开始时间-活动的时长

活动的最晚开始时间-活动的最早开始时间 = 0 的活动为关键活动

在这里插入图片描述

即关键路径为( v 1 , v 4 , v 7 , v 8 , v 10 , v 11 v_1,v_4,v_7,v_8,v_{10},v_{11} v1,v4,v7,v8,v10,v11)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AmosTian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值