posted on 2019-08-28 16:45:21
A.树的遍历
题目描述
给定一棵 \(n\) 个节点的无根树(节点编号 \(0\) 至 \(n-1\))和一个节点\(x\),请以 \(x\) 号节点为根,做一次 DFS 与一次 BFS。
输入格式
从标准输入读入数据。
第一行输入一个正整数 \(n\)(\(1 \leq n \leq 200000\)),代表这棵树的节点数目。
接下来 $ n-1 $ 行(行编号从 $ 1 $ 至 $ n-1 $),第 \(i\) 行输入一个正整数 $ a_i \((\) 0 \leq a_i \leq i $),代表第 \(i\) 个节点与第 $ a_i $ 个节点之间连有一条边。
最后一行输入 $ x \((\) 0 \leq x < n $),代表根节点编号。
输出格式
输出到标准输出。
输出 $ 2 $ 行,每行 $ n $ 个数,第 $ 1 $ 行代表 DFS 序,第 $ 2 $ 行代表 BFS 序。
注意:如果一个节点有多个儿子,那么应按照儿子编号递减的顺序去遍历。
样例1输入
7 0 1 0 0 1 4 1
样例1输出
1 5 2 0 4 6 3 1 5 2 0 4 3 6
解:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> #include <vector> using namespace std; vector<int> to[200005]; int n,a,vis[200005],q[200005],start; int cmp(int b,int c) { return b>c; } void ad(int u,int v) { to[u].push_back(v); } void dfs(int k) { cout << k << ' '; for(int i=0;i<to[k].size();i++) { if(vis[to[k][i]]==0) { vis[to[k][i]]=1; dfs(to[k][i]); } } } void bfs(int k) { int head=1,tail=1; q[tail]=k; tail++; while(head<tail) { int now=q[head]; cout << now << " "; head++; for(int i=0;i<to[now].size();i++) { if(vis[to[now][i]]==0) { vis[to[now][i]]=1; q[tail]=to[now][i]; tail++; } } } } int main() { cin >> n; for(int i=1;i<=n-1;i++) { cin >> a; ad(a,i); ad(i,a); } cin >> start; for(int i=0;i<n;i++) sort(to[i].begin(),to[i].end(),cmp); /*for(int i=0;i<n;i++) { for(int j=0;j<to[i].size();j++) cout << to[i][j] << " "; cout << endl; }*/ //对于有根树,将start换成根节点即可 vis[start]=1; dfs(start); memset(vis,0,sizeof(vis)); cout << endl; vis[start]=1; bfs(start); return 0; }
B.树的直径和中心
题目描述
给定一棵 \(n\) 个节点的无根树(节点编号 \(0\) 至 \(n-1\)),所有边长均为 \(1\),求出该树的直径长度。
定义树的中心为距离树上所有节点距离的最大值最小的节点(一棵树的中心可能不止一个),输出该树的中心。
输入格式
从标准输入读入数据。
第一行输入一个正整数 \(n\)(\(1 \leq n \leq 200000\)),代表这棵树的节点数目。
接下来 \(n-1\) 行(行编号从 \(1\) 至 \(n-1\)),第 \(i\) 行输入一个正整数 \(a_i\)(\(0 \leq a_i <i\)),代表第 \(i\) 个节点与第 \(a_i\) 个节点之间连有一条边。
输出格式
输出到标准输出。
输出 \(2\) 行,第 \(1\) 行一个整数,代表树的直径;第 \(2\) 行按照编号递增顺序输出若干个整数,代表树的中心节点编号。
样例1输入
6 0 1 0 0 1
样例1输出
3 0 1
解:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> #include <vector> using namespace std; vector<int> to[200005]; int n, a, vis[200005], q[200005], step[200005][2], head = 1, tail = 1, cen[3]; int cmp(int b, int c) { return b > c; } void ad(int u, int v) { to[u].push_back(v); } void bfs(int k) { head = 1; tail = 1; q[tail] = k; tail++; while (head < tail) { int now = q[head]; head++; for (int i = 0; i < to[now].size(); i++) { if (vis[to[now][i]] == 0) { vis[to[now][i]] = 1; q[tail] = to[now][i]; step[tail][0] = step[head - 1][0] + 1; step[tail][1] = head - 1; tail++; } } } } int main() { cin >> n; for (int i = 1; i <= n - 1; i++) { cin >> a; ad(a, i); ad(i, a); } for (int i = 0; i < n; i++) sort(to[i].begin(), to[i].end(), cmp); vis[0] = 1; bfs(0); int point = q[head - 1]; memset(vis, 0, sizeof(vis)); memset(step, 0, sizeof(step)); vis[point] = 1; bfs(point); int lenth = step[tail - 1][0]; cout << lenth << endl; if (lenth % 2 == 0) { for (int i = tail - 1; i > 0; i = step[i][1]) { if (step[i][0] == lenth / 2) { cen[1] = q[i]; cout << cen[1] << endl; return 0; } } } else { for (int i = tail - 1; i > 0; i = step[i][1]) { if (step[i][0] == (lenth + 1) / 2) { cen[1] = q[i]; } if (step[i][0] == (lenth - 1) / 2) { cen[2] = q[i]; if (cen[2] < cen[1]) swap(cen[2], cen[1]); cout << cen[1] << " " << cen[2] << endl; return 0; } } } }