九野的博客,转载请注明出处:http://blog.csdn.net/acmmmm/article/details/12683797
题目链接:http://cstest.scu.edu.cn/soj/problem.action?id=4313
#include
#include
#define N 200001
struct node{
int f,t,fn,tn,nex;//对于树的每条边,判断这条边左右端点的个数是否满足切割条件,是的话就统计
}edge[N];
int edgenum, head[N];
void addedge(int u, int v){
node E={u,v,0,0,head[u]};
edge[edgenum] = E;
head[u] = edgenum++;
}
int n,K,m; //n个点 m条边
int du[N],dp[N];//dp[i] 表示以i为父节点的子节点数
bool vis[N], use[N];//vis是搜索树利用的数组 use表示该点是否已被切割,一个点相连的边中只能有1条边被切割
int ans ;
void dfs(int x){
for(int i=head[x]; i!=-1; i = edge[i].nex){
int v = edge[i].t;
if(!vis[v]){
vis[v] = 1;
dfs(v);
dp[x] += dp[v];
edge[i].tn = dp[v];
edge[i].fn = n - edge[i].tn;
if(edge[i].tn %K==0 && !use[v] )ans++, use[v] = 1;
if(edge[i].fn %K==0 && !use[x] )ans++, use[x] = 1;
}
}
}
int main(){
int T,i,j;scanf("%d",&T);
while(T--){
scanf("%d %d",&n,&K);
memset(head,-1,sizeof(head)), edgenum = 0;
memset(du,0,sizeof(du));
m=n-1;
while(m--){
int u,v;scanf("%d %d",&u,&v);
addedge(u,v);
addedge(v,u);
du[u]++,du[v]++;
}
memset(vis,0,sizeof(vis));
memset(use,0,sizeof(use));
for(int i=1;i<=n;i++)dp[i] = 1;
ans = 0;
for(int i=1;i<=n;i++)//无根树转有根树
if(du[i] == 1)
{ vis[i]=1, dfs(i); break;}
if(ans>= n/K)printf("YES\n");
else printf("NO\n");
}
return 0;
}
/*
2
4 2
1 2
2 3
3 4
4 2
1 2
1 3
1 4
*/