题解 洛谷 P3915 【树的分解】
作者:互联网
1## P3915 树的分解
题目描述
给出\(N\)个点的树和K,问能否把树划分成\(\frac{N}{K}\)个连通块,且每个连通块的点数都是\(K\)。
解题思路
分析样例:
「\(sample1\)」
可被划分为\(1\).\(2\)、\(3\).\(4\)两个大小为\(2\)的连通块。
「\(sample2\)」
无法被划分为大小为\(2\)的连通块
我们可以整理出以下思路:
[1] 若总点数\(N\)无法被\(K\)整除,则无法被恰好分成\(\frac{N}{K}\)个连通块。
[2] 考虑统计每个子树的大小,在当前子树大小恰好为\(K\)时将其赋值为\(0\)(相当于删除)并将这个连通块计入答案中。
注意事项
多组测试数据时要将变量清零。
#include<bits/stdc++.h>
#define re register
#define il inline
#define MAXN 100005
#define rep(i,a,b) for(re int i = a;i <= b;++ i)
#define Rep(i,a,b) for(re int i = a;i < b;++ i)
#define drep(i,a,b) for(re int i = a;i >= b;-- i)
#define Drep(i,a,b) for(re int i = a;i > b;-- i)
#define star(i,x) for(re int i = head[x];i;i = e[i].nxt)
#define fin(a) freopen(#a".in","r",stdin)
#define fout(a) freopen(#a".out","w",stdout)
using namespace std;
il int read(){
int x = 0;
char ch = 0;
while(!isdigit(ch))
ch = getchar();
while(isdigit(ch)){
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return x;
}
il void write(int x){
if(x > 9)
write(x / 10);
write(x % 10 + '0');
}
struct edge{
int nxt,to;
}e[MAXN << 1];
int head[MAXN << 1],cnt = 0,ans = 0;
int t,n,k;
int siz[MAXN];
il void add(int u,int v){
e[++ cnt].to = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
il void dfs(int x,int fa){
siz[x] = 1;
star(i,x){
int v = e[i].to;
if(v != fa){
dfs(v,x);
siz[x] += siz[v];
}
}
if(siz[x] == k){
siz[x] = 0;
ans ++;
}
}
int main(){
#ifndef ONLINE_JUDGE
fin(3915);
fout(3915);
#endif
t = read();
while(t --){
n = read(),k = read();
ans = 0,cnt = 0;
memset(head,0,sizeof(head));
memset(siz,0,sizeof(siz));
memset(e,0,sizeof(e));
Rep(i,1,n){
int u = read(),v = read();
add(u,v);
add(v,u);
}
if(n % k != 0){
printf("NO\n");
continue;
}
dfs(1,0);
if(ans == n / k)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
标签:连通,ch,洛谷,int,题解,re,P3915,freopen,define 来源: https://www.cnblogs.com/StudyingVeyron-MUST/p/16675889.html