树的基础

1.时间戳

int dfn[N],vis[N],cnt;
void dfs(int u) {
	vis[u]=1;
	dfn[u]=++cnt;//时间戳
	for(int i=h[u]; ~i; i=ne[i]) {
		int j=e[i];
		if(vis[j])continue;
		dfs(j);
	}
}

2.树的dfs序:长度为2n

性质:某节点x从第一次被标记在节点序列中到第二次被标记之间的节点序列就是以x为根节点的子树的dfs序

int a[N],tot=0;
void dfs(int u) {
	a[++tot]=u;
	vis[u]=1;
	for(int i=h[u]; ~i; i=ne[i]) {
		int j=e[i];
		if(vis[j])continue;
		dfs(j);
	}
	a[tot++]=u;
}

3.树的深度(两种方法)

int vis[N],dep[N];
void dfs(int u) {
	vis[u]=1;
	for(int i=h[u]; ~i; i=ne[i]) {
		int j=e[i];
		if(vis[j])continue;
		dep[j]=dep[u]+1;
		dfs(j);
	}
}

//bfs求图的每一层,d[]存点到1的距离
void bfs() {
	memset(d,0,sizeof(d));
	queue<int>q;q.push(1);d[1]=1;
	while(q.size()) {
		int t=q.top;q.pop();
		for(int i=h[t]; ~i; i=ne[i]) {
			int j=e[i];
			if(d[j])continue;
			d[j] = d[t] +1;
			q.push(j);
		}
	}
}

4.树的子树大小,重心:去点某个点后最大的连通块最小

int vis[N],sz[N];
void dfs(int u) {  //树的子树大小和重心
	vis[u]=1,sz[u]=1;
	int max_part=0;  //删除u结点后最大子树大小
	for(int i=h[u]; ~i; i=ne[i]) {
		int j = e[i];
		if(vis[j])continue;
		dfs(j);
		sz[u] += sz[j];
		max_part=max(max_part,sz[j]);
	}
	max_part=max(max_part,n-sz[u]);
	if(max_part < ans) {
		ans = max_part;   //去掉重心后的最大块
        pos = u;  //重心结点号
	}
}

5.图的连通块个数与划分

void dfs(int u) {
	vis[u] = cnt;
	for(int i=h[u]; ~i; i=ne[i]) {
		int j=e[i];
		if(vis[j])continue;
		dfs(j);
	}
}

for(int i=1; i<=n; i++) {
	if(!vis[i]) {cnt++;dfs(i);}
}

树的基础

上一篇:容器嵌套


下一篇:redis命令大全