CF: dfs and similar ?? *2000
题意:
题目定义了一种新的图,这里我们叫做 “k层树”,解释一下:
当k为1的时候,有一个点度数>=3,其余的点的度数都是1;
当k>=2的时候,把 k-1层图 看作一个结点度数为1的点,然后有一个结点(纯正的度数为1的结点)连接>=3个这样的结点;
现在给你一个这样的图,判断是不是 k层图;
输入n为结点个数,然后是k,然后n-1行表示边; (题目保证是一棵树)
思路:
我们假设这个图是k层图,然后我们把他按照一定的方式遍历,中途遇到不合法的情况退出,最后判断是否为k层
遍历方式:先把度数为1的结点找到,那么它连接的一定是“1层图”的中心点,然后删去这些度数为1的点,然后把跟他相连的点存起来,在下一层中,就把这些点看作一个度数为1的结点,然后还要记录当这些结点的叶子,得>=3;
复杂度 n*常数 吧;
#include<bits/stdc++.h>
using namespace std;
#define out fflush(stdout);
#define fast ios::sync_with_stdio(0),cin.tie(0);
#define FI first
#define SE second
typedef long long ll;
typedef pair<ll,ll> P;
const int maxn = 1e5 + 7;
const int INF = 0x3f3f3f3f;
const ll mod = 998244353;
int n, k;
set<int> st[maxn];
int cnt[maxn];
int d[maxn];
int main() {
scanf("%d%d", &n, &k);
if(n < 4) {
printf("No");
return 0;
}
int u, v;
for(int i = 1; i < n; ++i) {
scanf("%d%d", &u, &v);
st[u].insert(v);
st[v].insert(u);
d[u]++, d[v]++;
}
int num = 0;
set<int> t;
for(int i = 1; i <= n; ++i) {
if(d[i] == 1) {
int j = *st[i].begin();
t.insert(j);
cnt[j]++;
st[j].erase(st[j].find(i));
num++;
}
}
int ans = 1;
set<int> t_;
while(t.size()) {
if(t.size() == 1) {
int j = *t.begin();
if(cnt[j] < 3) {
printf("No");
return 0;
}
num++;
break;
}
for(auto i : t) {
if(cnt[i] < 3 || st[i].size() != 1) {
printf("No");
return 0;
}
int j = *st[i].begin();
t_.insert(j);
cnt[j]++;
st[j].erase(st[j].find(i));
num++;
}
t.clear();
for(auto i : t_) {
t.insert(i);
}
t_.clear();
ans++;
}
if(num != n) {
printf("No");
return 0;
}
if(ans == k) printf("Yes");
else printf("No");
return 0;
}