constint N = 1e5 + 10; //数据范围是10的5次方 constint M = 2 * N; //以有向图的格式存储无向图,所以每个节点至多对应2n-2条边
int h[N]; //邻接表存储树,有n个节点,所以需要n个队列头节点 int e[M]; //存储元素 int ne[M]; //存储列表的next值 int idx; //单链表指针 int n; //题目所给的输入,n个节点 int ans = N; //表示重心的所有的子树中,最大的子树的结点数目
bool st[N]; //记录节点是否被访问过,访问过则标记为true
//a所对应的单链表中插入b a作为根 voidadd(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx++; } //返回以u为根的子树中节点的个数,包括u节点 intdfs(int u){ int res = 0; //存储 删掉某个节点之后,最大的连通子图节点数 st[u] = true; //标记访问过u节点 int sum = 1; //存储 以u为根的树 的节点数, 包括u,如图中的4号节点
//访问u的每个子节点 for (int i = h[u]; i != -1; i = ne[i]) { int j = e[i]; //因为每个节点的编号都是不一样的,所以 用编号为下标 来标记是否被访问过 if (!st[j]) { int s = dfs(j); // u节点的单棵子树节点数 如图中的size值 res = max(res, s); // 记录最大联通子图的节点数 sum += s; //以j为根的树 的节点数 } }
//n-sum 如图中的n-size值,不包括根节点4; res = max(res, n - sum); // 选择u节点为重心,最大的 连通子图节点数 ans = min(res, ans); //遍历过的假设重心中,最小的最大联通子图的 节点数 return sum; }
int e[N], ne[N], h[N], idx; queue<int> q1; voidbfs(int x) {
q1.push(x); res_arr[x] = 0;
while (!q1.empty()) { int j = q1.front(); // q1.front() 是 idx,即元素下标,e[q1.front()] 是元素本身 q1.pop(); // i 指的是 idx 下标 for (int i = h[j]; i != -1; i = ne[i]) { int e_num = e[i]; if (!st[e_num]) { .................................. } } } }