• ”邻接表建图+图的遍历“教程(C++)


    教程1.存图建图

    我们都知道,

    图和树都由“点”和“边”组成

    (一条边连接两个点,下文将一条边指向的点叫做”儿子点“,另一个点则称作“父亲点”)

    所以我们只要把”边“与”点“的关系存下来

    就基本完成了图的储存

    那我们要记录的只有:

    一、针对每一个点:

            以当前点为父亲点的的第一条边

    二、针对每一条边:

            1.边的编号

            2.该边所指向的点(儿子节点)

            3.下一条以当前边连接的父亲节点为父亲节点的边

            4.点权(不少问题中都牵涉到点权,如最短路,最小生成树。。。可根据问题需要选择记录或不记录)

    CODE:

    1. //last[i]代表第一条以i为父亲节点的边(记录边的编号)
    2. int last[N*2]; //N*2 怕有双向边
    3. //cnt:边的编号
    4. int cnt;
    5. struct edge//存边
    6. {
    7. //to:这条边指向的儿子节点(记录点的编号)
    8. int to;
    9. //next下一条以当前边连接的父亲节点为父亲节点的边
    10. int next;
    11. //边的权值
    12. int value;
    13. } e[N*2];//下标为边的编号
    14. void insert(int u,int v,int val)// 建边(u为父亲点,v为儿子点)
    15. {
    16. //新加一条边 (编号++)
    17. ++cnt;
    18. //儿子节点为v
    19. e[cnt].to=v;
    20. //附上边权
    21. e[cnt].value=val;
    22. //更新当前第一条以u为父亲点的边
    23. e[cnt].next=last[u];
    24. last[u]=cnt;
    25. }
    26. int main()
    27. {
    28. // 如果我想建个图。。。(如下)
    29. // (括号里的数是边权)
    30. // 1
    31. // /
    32. // (1) /
    33. // /
    34. // 2
    35. // /\
    36. // (3) / \ (2)
    37. // / \
    38. // 3------4
    39. // (4)
    40. //如下建的是双向边(双向边建两次边,单向边只要一次)
    41. insert(1,2,1);
    42. insert(2,1,1);
    43. insert(2,3,3);
    44. insert(3,2,3);
    45. insert(2,4,2);
    46. insert(4,2,2);
    47. insert(3,4,4);
    48. insert(4,3,4);
    49. return 0;
    50. }

    教程2. 图的遍历:

    图的遍历我们一般采用DFS(深度优先)

    遍历顺序如下图

    很好写,直接上代码

    CODE:

    1. //vis[i]代表i被遍历过
    2. bool vis[N];
    3. void dfs(int x) {
    4. //打上标记,该点被遍历过
    5. vis[x]=1;
    6. for(int i=last[x]/*从第一条边开始*/;i;i=e[i].next/*跳到下一条边*/)
    7. {
    8. //如果此节点被遍历过,请跳过
    9. if(vis[e[i].to]) continue;
    10. //遍历儿子节点
    11. dfs(e[i].to);
    12. }
    13. }

    实战

    题目:树的结点计数

    Description

    第一行是一个整数N1\leqslantN\leqslant50000),表示计算机的台数,计算机被编号为1...N。 下面N-1行,每行包括两个整数X, Y,表示XY这两台计算机之间由一条网线连接。 1号点为根

    Format

    Input

    第一行给出数字N

    接下来N-1行描述这个树

    Output

    给出N行,分别表示从1号到N号点,每个点有多少个子结点

    Samples

    输入数据 1

    1. 3
    2. 1 2
    3. 1 3

    输出数据 1

    1. 2
    2. 0
    3. 0

    Limitation

    1s, 1024KiB for each  test case.

    CODE:

    1. #include
    2. using namespace std ;
    3. const int N=50000;
    4. int n,m;
    5. int a,b;
    6. int las[N*2];
    7. int cnt;
    8. int son[N];
    9. bool vis[N];
    10. struct edge
    11. {
    12. int to,last;
    13. } e[N*2];
    14. void insert(int u,int v)
    15. {
    16. ++cnt;
    17. e[cnt].to=v;
    18. e[cnt].last=las[u];
    19. las[u]=cnt;
    20. }
    21. void dfs(int x) {
    22. son[x]=1;
    23. vis[x]=1;
    24. for(int i=las[x];i;i=e[i].last) {
    25. if(vis[e[i].to]) continue;
    26. dfs(e[i].to);
    27. //加上每个儿子的子节点个数
    28. son[x]+=son[e[i].to];
    29. }
    30. }
    31. int main()
    32. {
    33. cin>>n;
    34. for(int i=1;i
    35. cin>>a>>b;
    36. insert(a,b);
    37. insert(b,a);
    38. }
    39. dfs(1);
    40. for(int i=1;i<=n;i++) {
    41. //输出时减去自己
    42. cout<-1<
    43. }
    44. return 0;
    45. }

  • 相关阅读:
    牛客SQL必会知识
    node插件MongoDB(四)—— 库mongoose 的文档操作使用
    Mybatis-Plus前后端分离多表联查模糊查询分页
    计算机毕业设计springboot交互式大学英语学习平台g9223源码+系统+程序+lw文档+部署
    李宏毅机器学习笔记:RNN循环神经网络
    Hive第一篇简介
    C语言& | ^
    seata环境的安装
    redis的原理和源码-数据持久化方式AOF的介绍和源码解析
    【Web前端】一文带你吃透HTML(上篇)
  • 原文地址:https://blog.csdn.net/ytk888/article/details/126354541