L2-026 小字輩 (25分)

徐龍潤發表於2020-11-08

本題給定一個龐大家族的家譜,要請你給出最小一輩的名單。
輸入格式:
輸入在第一行給出家族人口總數 N(不超過 100 000 的正整數) —— 簡單起見,我們把家族成員從 1 到 N 編號。隨後第二行給出 N 個編號,其中第 i 個編號對應第 i 位成員的父/母。家譜中輩分最高的老祖宗對應的父/母編號為 -1。一行中的數字間以空格分隔。
輸出格式:
首先輸出最小的輩分(老祖宗的輩分為 1,以下逐級遞增)。然後在第二行按遞增順序輸出輩分最小的成員的編號。編號間以一個空格分隔,行首尾不得有多餘空格。
輸入樣例:
9
2 6 5 5 -1 5 6 4 7
輸出樣例:
4
1 9

 #include<bits/stdc++.h>

using namespace std;
const int MAXN=100001;
int MAX=0;
vector<int> ve[MAXN];
struct node {
	int ceng,num;//分別為輩分 和編號 
	vector<int>ve;//儲存自己的孩子 
};
vector<node> t;//儲存輩分最小的編號 
bool cmp(node a,node b){ 
	return a.num<b.num;
}
//構建一個樹
//在構造樹的過程中計算題目要求求的量 
void fff(int root){
	queue<node> q;
	node temp;
	temp.ceng=1;
	temp.num=root;
	t.push_back(temp);
	//將最高輩分入隊 
	q.push(temp);
	while(!q.empty()){
		node now=q.front();
		q.pop();
		MAX=max(MAX,now.ceng);//記錄最小輩分 
		for(int i=0;i<ve[now.num].size();i++){
			int x=ve[now.num][i];
			temp.num=x;
			temp.ceng=now.ceng+1;//孩子的輩分等於父母輩分加一 
			temp.ve=ve[x];
				q.push(temp);
				//如果當前的輩分和t裡面存的最小輩分相同
				//則入隊 
				if(temp.ceng==t[0].ceng) {
					t.push_back(temp);
				}
				//如果不相同則說明t裡面存的不是最小輩分
				//清空t  並且把temp加入 
				else{
					t.clear();
					t.push_back(temp);
				} 
		}
	}
}
int main(){
	int n;
	int root;//記錄最高輩分 
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		int x;
		scanf("%d",&x);
		if(x!=-1)ve[x].push_back(i);// 記錄x的孩子 
		else root=i;//記錄最高輩分 
	}
	fff(root);
	printf("%d\n",MAX);
	sort(t.begin(),t.end(),cmp);// 把最小輩分的編號排序 
	for(int i=0;i<t.size();i++){
		if(i==0) printf("%d",t[i].num);
		else printf(" %d",t[i].num);
	}
	return 0;
}

相關文章