1. 程式人生 > 實用技巧 >葉子清除計劃【第五週】 題解

葉子清除計劃【第五週】 題解

葉子清除計劃【第五週】

題目描述

⼩Y同學是⼀位資料結構⼤師同時也是⼀位園藝⼤師。

秋天到了,⼩Y同學需要對學校內的⼀棵樹展現他頂尖的修葉⽔平。

學校內的這棵樹是⼀顆擁有n個點的⽆根樹,每次⼩Y會刪去所有的葉⼦節點(即度數小於等於1的節點),直到所有的點都被刪除了為⽌。

⼩Y現在想問你對於每個點,求出它是第⼏次操作中被刪除的。

輸入格式

第⼀⾏⼀個數字n,表⽰樹上節點個數

接下來n−1⾏,每⾏兩個數字u,v,表⽰樹上的⼀條邊。

輸出格式

⼀⾏n個數字,第i個數字表⽰節點i在第⼏次操作中被刪除。

樣例

樣例輸入1:

5
1 2
1 3
2 4
2 5

樣例輸出1:

2 2 1 1 1

樣例輸入2:

4
1 2
1 3
1 4

樣例輸出2:

2 1 1 1

資料範圍與提示

對於30%的資料,n≤1000

對於100%的資料,2≤n≤100000,1≤u,v≤n

分析

首先看到題目,所給樹是一棵無根樹,一棵沒有特定的根節點的樹,稱為無根樹。
所以任意選取圖中某個點為根,均可將無根樹轉化成為有根樹,即在輸入時要雙向加邊。
因為每次是要將葉子節點刪去,那麼當入度為1時(假設此邊所連點為根節點,此節點就是葉子節點),就應該刪掉。
題目要求刪除的順序,所以就定義一個結構體,儲存入度刪除的次序,通過以上推論可得刪掉的節點的次序就應該是它倒數第二條邊所連線的節點的次序加一
用拓撲序變形就可解決。
分析至此,不難寫出程式碼.

程式碼

#include <queue>
#include <vector>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 100005;

int n;
vector<int> G[MAXN]; 

struct node {
	int in, flo;
} a[MAXN];

queue<int> q;

void topsort() {
	for (int i = 1; i <= n; i++) {
		if (a[i].in == 1) {
			q.push(i);
			a[i].flo = 1;
		}
	}
	while (q.size()) {
		int u = q.front();
		q.pop();
//		printf ("%d: ", u);
		for (int i = 0; i < G[u].size(); i++) {
			int v = G[u][i];
			a[v].in --;
			if (a[v].in == 1) {
//				printf ("%d ", v);
				a[v].flo = a[u].flo + 1;
				q.push(v);
			}
		}
//		printf ("\n");
	}
}

int main() {
	scanf ("%d", &n);
	for (int i = 1, u, v; i < n; i++) {
		scanf ("%d %d", &u, &v);
		G[u].push_back(v);
		G[v].push_back(u);
		a[u].in ++, a[v].in ++;
	}
//	for (int i = 1; i <= n; i++) {
//		printf ("%d %d\n", a[i].flo, a[i].in);
//	}
	topsort();
	for (int i = 1; i <= n; i++) {
		printf ("%d ", a[i].flo);
	}
	return 0;
}