1. 程式人生 > >Codeforces Round #518 (Div. 1)B(模擬,尋找多叉樹的根,dfs)

Codeforces Round #518 (Div. 1)B(模擬,尋找多叉樹的根,dfs)

題意

題目的意思挺難懂的,簡單的來說,就是判斷一個kk叉樹是否由一個k1k-1叉樹而來。這裡對kk叉樹的定義是:

  1. 對於11叉樹,僅有一個點度數為33且度數為11的點個數大於等於3。
  2. 對於k(k2)k(k\geq2)叉樹,是一個點連線33個或33個以上的(k1)(k-1)叉樹所構成。

題解

這題主要就是需要找到樹根,如果找到了樹根那麼就可以進行dfs判斷是否為合格的k叉樹,但如果找樹根呢?一種辦法是求出樹的直徑,然後根據直徑長度的一半找到樹根,還有一種方法便是,由於這顆樹是一層一層擴展出去的,所以只要一層一層往裡走,就可以找到樹根,類似圓慢慢縮小。 因為每層都是一樣的,所以dfs判斷的話就是遞迴k層判斷即可(注意特殊處理一下最後一層)。

程式碼

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
vector<int> G[maxn];
int que[maxn], l,r, de[maxn], pre[maxn];
void add(int f,int t) {
	G[f].push_back(t);
}
// 樹的直徑
int bfs(int o) {
	l = r = 0;
	que[r++] = o;
	memset(de, -1, sizeof de);
	de[o] = 0;
	pre[o] = -1;
	while
(l <= r) { int u = que[l++]; for(int i = 0; i < G[u].size(); ++i) { int to = G[u][i]; if(de[to] != -1) continue; pre[to] = u; de[to] = de[u]+1; que[r++] = to; } } return que[r-1]; } // 檢驗樹根 bool check(int o, int fa, int k) { if(k == 0) { int son = 0; for(int i = 0; i <
G[o].size(); ++i) { int to = G[o][i]; if(to == fa) continue; son++; } if(son > 0) return false; return true; } int cnt = 0; for(int i = 0; i < G[o].size(); ++i) { int to = G[o][i]; if(to == fa) continue; if(!check(to, o, k-1)) return false; cnt++; } if(cnt < 3) return false; return true; } int main() { int n,k,u,v; scanf("%d%d", &n, &k); for(int i = 0; i < n-1; ++i) { scanf("%d%d", &u, &v); add(u,v); add(v,u); } u = bfs(1); v = bfs(u); if(de[v]%2 != 0) puts("No"); else { int center = v; for(int i = 0; i < de[v]/2; ++i) center = pre[center]; // cout << center << endl; if(check(center, -1, k)) puts("Yes"); else puts("No"); } return 0; }