Codeforces Round #670 (Div. 2) C. Link Cut Centroids (dfs traverse tree, centroid)

C. Link Cut Centroids

C. Link Cut Centroids
question meaning: given a tree of n nodes, suppose that among the n nodes, if one of the nodes k (including all the edges contained in the node) is removed, the largest point contained in each connected block The number of is the smallest, then node k is the centroid of the tree.
Now there are two operations

  1. Select two nodes a 1, a 2 a_1, a_2a1a2And delete the edge between the two
  2. Select two nodes a 1, a 2 a_1, a_2a1,a2Connecting the two points
    requires that the centroid of the tree is unique after two operations.

Idea:
Carefully observe the graph with two centroids given in the title:
Points 1, 2 are the two centroids of this picture

Then make a few pictures by hand, you can find

  1. Only two centroids at most
  2. If there are 2 centroids, then the tree must have symmetry
  3. If there are two centroids, there must be no other points between them (because they are symmetrical. If there are an odd number of points in the middle, then the center of mass is the center of mass; if there is an even number of points in the middle, then push to the middle adjacent Point is the centroid)
    then the overall code is relatively simple
  • Taking node 1 as the root, dfs traverses the tree, counts the number of sons of each point (including itself), and records it in son [] son ​​[]s o n [ ] array, record the parent nodef [] f[]at the same timef [ ] (Two judgments are used in the subsequent counting)
  • Traverse all n nodes, assuming that the iiThe i nodes are removed, and then each adjacent node is searched for the number of nodes in the connected block where they are:
    • Father node = n − son [i] n-son[i]nson[i]
    • Son node kkk =are [k] are [k]son[k]
  • Just take the maximum value, and then make a structure cun [] cun[]c u n [ ] Record the maximum number of nodes in the connected block after removing himnum numn u m and current own node subscriptid idid s o r t sort sort

Finally, look at the num num of the largest and second largest nodesAre n u m the same

  • Same: There are two centroids, remove the middle line, and even the son of one to the other
  • Not the same: there is only one centroid, just find an edge and add it ^^
int f[maxn], son[maxn], co, n, t;
vector<int> G[maxn];
struct node {
    
    
	int num, id;
}cun[maxn];
bool cmp(node a, node b) {
    
    
	return a.num < b.num;
};
int dfs(int fa, int nw) {
    
    
	f[nw] = fa;
	int sum = 1;
	for (int i = 0; i < G[nw].size(); i++) {
    
    
		if (G[nw][i] == fa)continue;
		sum += dfs(nw, G[nw][i]);
	}
	return son[nw] = sum;
}
int main()
{
    
    
	cin >> t;
	int u, v;
	while (t--)
	{
    
    
		cin >> n;
		for (int i = 1; i <= n; i++)G[i].clear();
		co = 0;
		for (int i = 1; i < n; i++) {
    
    
			cin >> u >> v;
			G[u].push_back(v);
			G[v].push_back(u);
		}
		dfs(0, 1);
		int maxx;
		for (int i = 1; i <= n; i++) {
    
    
			maxx = 0;
			for (int j = 0; j < G[i].size(); j++) {
    
    
				if (G[i][j] == f[i]) {
    
    
					maxx = max(maxx, n - son[i]);
				}
				else {
    
    
					maxx = max(maxx, son[G[i][j]]);
				}
			}
			cun[++co].id = i;
			cun[co].num = maxx;
		}
		sort(cun + 1, cun + 1 + n, cmp);
		int ans;
		if (cun[1].num == cun[2].num) {
    
    
			for (int i = 0; i < G[cun[1].id].size(); i++) {
    
    
				ans = G[cun[1].id][i];
				if (G[cun[1].id][i] != cun[2].id)break;
			}
			cout << cun[1].id << " " << ans << endl;
			cout << ans << " " << cun[2].id << endl;
		}
		else {
    
    
			ans = G[cun[1].id][0];
			cout << cun[1].id << " " << ans << endl;
			cout << cun[1].id << " " << ans << endl;
		}
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_44986601/article/details/108674117