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

C.リンクカットの重心

C. Link Cut Centroidsの
質問の意味:n個のノードのツリーが与えられた場合、n個のノードの中で、ノードk(ノードに含まれるすべてのエッジを含む)の1つが削除されると、接続された各ブロックに含まれる最大のポイントとなるの数が最小で、ノードkがツリーの重心です。
今、2つの操作があります

  1. 2つのノードa 1、a 2 a_1、a_2を選択しますa1a2そして、2つの間のエッジを削除します
  2. 2つのノードa 1、a 2 a_1、a_2を選択しますa1a22つのポイントを接続するには、2
    つの操作後のツリーの重心が一意である必要があります。

アイデア:
タイトルに与えられた2つの重心でグラフを注意深く観察します。
ポイント1、2はこの画像の2つの重心です

その後、手でいくつかの写真を作る、あなたは見つけることができます

  1. 最大で2つの重心のみ
  2. 2つの重心がある場合、ツリーは対称でなければなりません
  3. 2つの重心がある場合、それらの間に他のポイントがあってはなりません(それらは対称的であるためです。中央に奇数のポイントがある場合、重心は重心です。中央に偶数のポイントがある場合、隣接する中央に押します。ポイントは重心です)
    全体のコードは比較的単純です
  • ノード1をルートとして、dfsはツリーを走査し、各ポイント(それ自体を含む)の息子の数をカウントし、それをson [] son []に記録しますs o n [ ]配列、親ノードf [] f []を同時に記録f [ ](後続のカウントでは2つの判断が使用されます)
  • iiを想定して、すべてのnノードをトラバースします。iノードが削除され、次に隣接ノードごとに、接続されているブロック内のノードの数が検索されます。
    • 父ノード= n −息子[i] n-son [i]s o n [ i ]
    • 息子ノードKKk =are [k] are [k]s o n [ k ]
  • 最大値を取り、構造体cun [] cun []を作成するだけですc u n [ ]彼を削除した後、接続されたブロック内のノードの最大数を記録するnum numn u mおよび現在の自身のノードの添え字ID idi dsort sortS O のR T

最後に、最大および2番目に大きいノードのnum numを見てください。ある N Uはmは同じ

  • 同じ:重心が2つあり、中央の線を削除し、さらに片方の息子を削除します
  • 同じではありません。重心は1つしかありません。エッジを見つけて追加してください^^
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;
}

おすすめ

転載: blog.csdn.net/weixin_44986601/article/details/108674117