图论基础01学习

今天开始学习图论相关的算法。

今天学习内容:

图论相关概念,图的两个存储结构,图的bfs,dfs遍历,拓扑序。

  •  1,图论相关概念

# 图

vertex:点

edge:边 或顶点偶对称

有向图: <x, y> 由x--> y;

无向图: (x,y) NOTICE:特殊的有向图

## 图的基本术语

完全图:n(n-1)/2 -- 无向图 不除二 -- 有向图

权和网:

    权:每条边上可以标上具有某种含义的数值,该数值为权。可以表示距离或耗费。

    网:带权的图

邻接点:两点可相连

度:

    顶点v的度是指和v相关联的边的数目。记为:TO(v);

    入度:以顶点v为头的弧的数目。记为:ID(v);

    出度:以顶点v为尾的弧的数目。记为:OD(v)

    **TO(v) = ID(v) + OD(v)**

路径和路径长度:

回路或环

连通,连通图和连通分量:

    再G中,如果v->v'有路径,表示v和v'是连通的

    全部都是连通的,是连通图

    连通分量 是连通子图。



 

## 图的存储结构

### 邻接矩阵:

    就是二维数组,g[a,b] a-->b O(n*2)

### 邻接表

    图的链式存储结构。在邻接表中,对图中每一个顶点vi建立一个单链表

## 拓扑序列:有向图 都是从前指向后的

    有向无环图,被称为拓扑图

    有向无环图一定至少存在一个入度为0的点


 

## 最短路

 ### 单源最短路

    #### 所有边权都是正数

        1, 朴素Dijkstra算法

        2, 堆优化版的Dijkstra算法

    #### 存在负权边

        1, Bellman-Ford

        2, SPFA

 ### 多源汇最短路

    Floyd算法

 源点 起点  汇点 终点

  • 2,图的两个存储结构

        第一种:邻接矩阵。二维数组ph[][]   -- 适用于稠密表

        第二种:邻接表。用数组模拟链表。 -- 适用于稀疏表。

重点讲一下邻接表:

全局变量: h[] e[] ne[] idx;

//初始化:
void init() {
    memset(h,-1,sizeof(h) ); // <cstring>
}
// 增添;
void add(int a, int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

注意头结点的初始化,这个容易忘掉。

  • 3,遍历

      遍历主要分为bfs和dfs两个遍历。

BFS:

void bfs() {
    int hh = 0, tt = 0; // q[]  数组模拟队列

    // 入列

    while(hh <= tt) { // hh <= tt -- > 队列不为空
        int t = q[hh++]; // 出队
        for(int i = h[t]; i != -1; i = ne[i]) { // 邻接表
            int j = e[i];
            if(d[j] == -1) {
                // 执行
                q[++t] = j; // 入队
            }
        }
    }
    // 产生结果
}

DFS:

void dfs(int u) {
    int sum = 1, res = 0;
    for(int i = h[u]; i != -1; i = ne[i]) {
        int j = e[i];
        if(!st[j]) {
            // 过程
            dfs(j);
        }
    }
    // 结果
}
  • 4,拓扑排序

有向无环图(DAG。顶点的线性排序

所需算法:邻接表,队列

算法步骤:

  1.  遍历。将入度为0的点入队。
  2.  出列,弹出。邻接点入度减一,若邻接点入度为0就入队。
  3.  判断入队个数与顶点个数,相等表示是有向无环图,可以进行拓扑排序,反之有环不可以。

        d[] 表示点的入度。

bool toposort() {
    int hh = 0, tt = -1; // 模拟队列
    for(int i = 1; i <= n; ++i) { 
        if(d[i]) q[++tt] = i; // 入度0的入队    
    }
    while(hh <= tt) {
        int t = q[hh++];
        for(int i = h[t]; i != -1; i = ne[i]) {
            int j = e[i];
            d[j]--;
            if(d[j] == 0) q[++tt] = j;
        }
    }
    return tt == n-1; // true -- 有向无环图
}
  • 5,做题巩固。

在洛谷上做了P3916 图的遍历和P2712 摄像头,都是拓扑模板题。

P3916 图的遍历 解题思路:反建图,dfs,画个图看看就出来了。

P2712 摄像头 解题思路:去掉没有摄像头的区间,其他的拓扑排序,按上面模板来。

做题总结:算法思路很好理解,就是写的时候像点,邻接点,入度等会搞混,头结点没有赋初值 ( memset(h,-1,sizeof(h) ) )。学到了许多。像第二题,用vector<int>存可能size为0,这个时候size() == 0 但是由于size范围不是int型,会导致size()-1是很大的值,所以以后用size()时候要先用int存一下,进行类型转换,防止过大。

今日总结:图的知识有点绕,算法和算法模板好理解,就是总是丢三落四,让算法题AC不了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

golemon.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值