描述较抽象,以题目为例展示邻接表存图的用法,题目传送门
# 题目背景
# 题目大意
给定一颗树,树中包含 n 个结点(编号 1→n)和 n−1 条无向边。
请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。
重心定义:
重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。
# 输入格式
第一行包含整数 n,表示树的结点数。
接下来 n−1 行,每行包含两个整数 a 和 b,表示点 a 和点 b 之间存在一条边。
# 输出格式
输出一个整数 m,表示将重心删除后,剩余各个连通块中点数的最大值。
# 数据范围
1≤n≤105
# 解题代码
c++1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| #include<iostream> #include<cstring> using namespace std; const int N = 1e5 + 10, M = N * 2;
int n; int h[N], e[N], ne[M], idx, ans = N;
bool st[N];
void add(int a, int b)
{ e[idx] = b; ne[idx] = h[a]; h[a] = idx; idx++; }
int dfs(int u)
{ int res = 0, sum = 1; st[u] = true; for(int i = h[u]; i != -1; i = ne[i]) { int j = e[i]; if(!st[j]) { int s = dfs(j); res = max(res, s); sum += s; } } res = max(res, n - sum); ans = min(res, ans); return sum; }
int main() { memset(h, -1, sizeof(h)); cin >> n; for(int i = 0; i < n - 1; i++) { int a, b; cin >> a >> b; add(a, b); add(b, a); } dfs(1); cout << ans << endl; return 0; }
|