我们都知道,
图和树都由“点”和“边”组成
(一条边连接两个点,下文将一条边指向的点叫做”儿子点“,另一个点则称作“父亲点”)
所以我们只要把”边“与”点“的关系存下来
就基本完成了图的储存
那我们要记录的只有:
一、针对每一个点:
以当前点为父亲点的的第一条边
二、针对每一条边:
1.边的编号
2.该边所指向的点(儿子节点)
3.下一条以当前边连接的父亲节点为父亲节点的边
4.点权(不少问题中都牵涉到点权,如最短路,最小生成树。。。可根据问题需要选择记录或不记录)
- //last[i]代表第一条以i为父亲节点的边(记录边的编号)
- int last[N*2]; //N*2 怕有双向边
-
- //cnt:边的编号
- int cnt;
-
- struct edge//存边
- {
-
- //to:这条边指向的儿子节点(记录点的编号)
- int to;
-
- //next下一条以当前边连接的父亲节点为父亲节点的边
- int next;
-
- //边的权值
- int value;
-
- } e[N*2];//下标为边的编号
-
- void insert(int u,int v,int val)// 建边(u为父亲点,v为儿子点)
- {
-
- //新加一条边 (编号++)
- ++cnt;
-
- //儿子节点为v
- e[cnt].to=v;
-
- //附上边权
- e[cnt].value=val;
-
- //更新当前第一条以u为父亲点的边
- e[cnt].next=last[u];
- last[u]=cnt;
-
- }
- int main()
- {
- // 如果我想建个图。。。(如下)
- // (括号里的数是边权)
-
- // 1
- // /
- // (1) /
- // /
- // 2
- // /\
- // (3) / \ (2)
- // / \
- // 3------4
- // (4)
-
-
- //如下建的是双向边(双向边建两次边,单向边只要一次)
- insert(1,2,1);
- insert(2,1,1);
-
- insert(2,3,3);
- insert(3,2,3);
-
- insert(2,4,2);
- insert(4,2,2);
-
- insert(3,4,4);
- insert(4,3,4);
-
- return 0;
- }
图的遍历我们一般采用DFS(深度优先)
遍历顺序如下图

很好写,直接上代码
- //vis[i]代表i被遍历过
- bool vis[N];
-
- void dfs(int x) {
-
- //打上标记,该点被遍历过
- vis[x]=1;
-
- for(int i=last[x]/*从第一条边开始*/;i;i=e[i].next/*跳到下一条边*/)
- {
-
- //如果此节点被遍历过,请跳过
- if(vis[e[i].to]) continue;
-
- //遍历儿子节点
- dfs(e[i].to);
-
- }
- }
第一行是一个整数
(



),表示计算机的台数,计算机被编号为
。 下面
行,每行包括两个整数
,
,表示
和
这两台计算机之间由一条网线连接。
号点为根
第一行给出数字
接下来
行描述这个树
给出N行,分别表示从1号到N号点,每个点有多少个子结点
- 3
- 1 2
- 1 3
- 2
- 0
- 0
-
1s, 1024KiB for each test case.
- #include
- using namespace std ;
- const int N=50000;
- int n,m;
- int a,b;
- int las[N*2];
- int cnt;
- int son[N];
- bool vis[N];
- struct edge
- {
- int to,last;
- } e[N*2];
-
- void insert(int u,int v)
- {
- ++cnt;
- e[cnt].to=v;
- e[cnt].last=las[u];
- las[u]=cnt;
- }
-
- void dfs(int x) {
- son[x]=1;
- vis[x]=1;
- for(int i=las[x];i;i=e[i].last) {
- if(vis[e[i].to]) continue;
- dfs(e[i].to);
- //加上每个儿子的子节点个数
- son[x]+=son[e[i].to];
- }
- }
- int main()
- {
- cin>>n;
- for(int i=1;i
- cin>>a>>b;
- insert(a,b);
- insert(b,a);
- }
- dfs(1);
- for(int i=1;i<=n;i++) {
- //输出时减去自己
- cout<
-1< - }
- return 0;
- }
-
相关阅读:
【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