E. Multihedgehog
题意
给你一颗n个节点的树,让你判断是不是刺猬数给你一颗n个节点的树,让你判断是不是刺猬数给你一颗n个节点的树,让你判断是不是刺猬数
1层刺猬树的定义为, 有一个节点度数>=3 其余节点度数为11层刺猬树的定义为,\ 有一个节点度数>=3 \ 其余节点度数为11层刺猬树的定义为, 有一个节点度数>=3 其余节点度数为1
k层刺猬树的定义为,有一个节点的度数>=3 其余节点为一颗k−1层树的根k层刺猬树的定义为,有一个节点的度数>=3 \ 其余节点为一颗k-1层树的根k层刺猬树的定义为,有一个节点的度数>=3 其余节点为一颗k−1层树的根
1<=n<=105,1<=k<=1091<=n<=10^5,1<=k<=10^91<=n<=105,1<=k<=109
做法
首先一颗k层刺猬树有最少节点数首先一颗k层刺猬树有最少节点数首先一颗k层刺猬树有最少节点数
所以先判断一下n是否大于等于k层刺猬树所需节点数所以先判断一下n是否大于等于k层刺猬树所需节点数所以先判断一下n是否大于等于k层刺猬树所需节点数
之后重复这样一个过程,每次找出度数为1的点,把与他们相连的点丢尽vector,之后重复这样一个过程,每次找出度数为1的点,把与他们相连的点丢尽vector,之后重复这样一个过程,每次找出度数为1的点,把与他们相连的点丢尽vector,
并在与他们相连的点的set种删除本点并在与他们相连的点的set种删除本点并在与他们相连的点的set种删除本点
丢进vector的点sum++丢进vector的点sum++丢进vector的点sum++
如果他们满足每个点的sum>=3,就重复这个过程如果他们满足每个点的sum>=3,就重复这个过程如果他们满足每个点的sum>=3,就重复这个过程
最后看k层之后是否只剩下一个点,而且这个点的度数>=3最后看k层之后是否只剩下一个点,而且这个点的度数>=3最后看k层之后是否只剩下一个点,而且这个点的度数>=3
代码
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
#include<set>
using namespace std;
typedef long long ll;
#define dbg(x) cout<<#x<<" = "<<x<<endl;
const int maxn = 1e5+10;
map<int,int> mp1,mp2;
set<int> s[maxn];
int sum[maxn];//记录每个点有多少个儿子
int vis[maxn];
vector<int> tmp[2];//存每次前驱的id
int main()
{
int n,k,u,v;
scanf("%d%d",&n,&k);
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&u,&v);
s[u].insert(v);
s[v].insert(u);
}
ll tm=1;
for(int i=1;i<=k;i++)
{
tm=tm*3LL;
if(tm>(2*n+1))
{
printf("No\n");
return 0;
}
}
int flag=0;
for(int i=1;i<=n;i++)
{
if(s[i].size()==1)
{
sum[i]=3;
tmp[1].push_back(i);
}
}
for(int i=1;i<=k;i++)
{
tmp[(i+1)%2].clear();//vector是滚动的,用两个vector达到目的
for(int j=0;j<tmp[i%2].size();j++)
{
if(sum[tmp[i%2][j]]<3||s[tmp[i%2][j]].size()!=1)
//如果有一个点不满足sum大于3
//或者这个点还存在超过两个边
{
flag=1;
break;
}
else
{
int tt=*s[tmp[i%2][j]].begin();
int tt2=tmp[i%2][j];
s[tt].erase(tt2);//在相连的点的边种删除本条边
sum[tt]++;
if(vis[tt]) continue;
else
{
tmp[(i+1)%2].push_back(tt);
vis[tt]=1;
}
}
}
if(flag==1) break;
}
if(flag==0&&tmp[(k+1)%2].size()==1&&sum[tmp[(k+1)%2][0]]>=3&&s[tmp[(k+1)%2][0]].size()==0) printf("Yes\n");
//flag=0 表示满足刺猬树属性
//tmp[(k+1)%2].size()==1表示最后的点为根
//sum[tmp[(k+1)%2][0]]>=3 表示根节点满足度数>=3
//s[tmp[(k+1)%2][0]].size()==0表示最后根节点不再有其他儿子
else printf("No\n");
return 0;
}