• ”邻接表建图+图的遍历“教程(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. }

  • 相关阅读:
    【C++】自旋锁
    颠覆IoT行业的开发神器!涂鸦智能重磅推出TuyaOS操作系统【程序员必备】
    git merge本地合并分支出现文件冲突处理方法
    RK3399应用开发 | RK3399本地编译glmark2
    Nginx 配置 HTTPS 过程(+反向代理)
    Java项目_在线点餐系统(jsp+sevlet+mysql)(含论文)
    Linux Kafka 3.5 KRaft模式集群部署
    US1MF-ASEMI贴片快恢复二极管US1MF
    栈的应用-综合计数器的实现
    算法设计与分析 | 输油管道
  • 原文地址:https://blog.csdn.net/ytk888/article/details/126354541