PAT.A1021最も深いルート

目次に戻るここに画像の説明を挿入

タイトル

n個のノードとn-1個のエッジを与える。nノードのツリーを形成できるかどうか尋ねますか?可能であれば、出力ノードがツリーのルートとして使用されるため、ツリーの高さが最大化され、満たされたすべてのノードが出力されます。そうでない場合は、接続されているブロックの数が出力されます。

サンプル(コピー可能)

5
1 2
1 3
1 4
2 5
//output
3
4
5
5
1 3
1 4
2 5
3 4
//output
Error: 2 components

注意点

  1. この問題を解決するには、2つの問題があります:①ツリーを形成できるかどうかを決定する②ツリーを形成できるときの条件を満たすノードを見つける
  2. ①の問題については、チェックセットやDFSの方法で接続ブロック数を求めることができますが、block = 1の場合はツリーを形成することができます。この質問では、DFS方式を使用しています。
  3. 問題2には2つの解決策があります。1つ目は、任意のノードの最も遠いノードのセットAを見つけ、Aのノードを選択して、最も遠いノードのセットBを見つけます。AとBの和集合は、条件を満たすすべてのノードはここでは省略されます。このメソッドを使用してコレクションを使用する場合、結合する関数set_union()を含むSTLライブラリセットを使用できます。次に、各ノードをルートノードとして使用する場合のツリーの最大の高さを見つけ、最後に最大の高さを比較して、条件を満たすノードを取得します。この質問では後者を使用します。
#include<bits/stdc++.h>
using namespace std;

const int N=100010;
vector<int> G[N];
bool flag[N]={false};//标记节点是否访问过 
int n,block=0;//节点数,连通块数
int maxdepth[N],depth[N];//maxdepth记录每个节点的最大深度,depth记录到root的距离 
void DFS(int v,int root){
	flag[v]=true;
	for(int i:G[v]){
		if(!flag[i]){
			depth[i]=depth[v]+1;//当前结点深度为其父节点深度+1
            maxdepth[root]=max(maxdepth[root],depth[i]);//更新树的深度
            DFS(i,root);
		}
	}
}
int main(){
	cin>>n;
	int a,b; 
	for(int i=1;i<n;i++){//输入n-1条边 
		scanf("%d %d",&a,&b);
		G[a].push_back(b);
		G[b].push_back(a);
	}
	for(int i=1;i<=n;i++){
		if(!flag[i]){
			DFS(i,i);
			block++;
		}
	}
	if(block>1){
		printf("Error: %d components\n",block);
	}else{
		for(int i=2;i<=n;i++){//i=1必然遍历过了
            memset(depth,0,sizeof(depth));
            memset(flag,false,sizeof(flag));
            DFS(i,i);
        }
        vector<int> ans;//存储为根节点时使树的深度最大的结点
        int deep=0;//查找所有为根节点时使树的深度最大的结点
        for(int i=1;i<=n;i++)
            if(maxdepth[i]>deep){
                ans.clear();
                ans.push_back(i);
                deep=maxdepth[i];
            }else if(maxdepth[i]==deep)
                ans.push_back(i);
        for(int i:ans)printf("%d\n",i);
	}
    return 0;
}
公開された177元の記事 ウォンの賞賛5 ビュー6656

おすすめ

転載: blog.csdn.net/a1920993165/article/details/105555810