嘘~ 正在从服务器偷取页面 . . .

洛谷P3915 树的分解 题解


洛谷P3915 树的分解 题解

题目链接:P3915 树的分解

题意

给出 $N$ 个点的树和 $K$,问能否把树划分成 $\frac{N}{K}$ 个连通块,且每个连通块的点数都是 $K$。

输入格式

第一行,一个整数 $T$,表示数据组数。接下来 $T$ 组数据,对于每组数据:

第一行,两个整数 $N, K$。

接下来 $N - 1$ 行,每行两个整数 $A_i, B_i$,表示边 $(A_i, B_i)$。点用 $1, 2, \ldots, N$ 编号。

输出格式

对于每组数据,输出 YESNO

数据范围

对于 $100 \%$ 的数据,$1 \le T \le 10$,$1 \le N ,K \le 10^5$。

贪心好题。

首先 $n \bmod k \ne 0$ 肯定无解。

考虑从下往上依次考虑每个点

如果它的 $\mathtt{sz}_u = k$ 那就把它的砍掉,并令 $\mathtt{sz}_u \gets 0$

在有解的情况下,这么做一定可以分出来。

如果某个 $\mathtt{sz}_u > k$ 怎么办呢? 可以发现此时一定无解,根据归纳法可证。

因为此时如果强行切出一个 $k$ 的块,则 $u$ 至少有一个儿子 $v$ 无法被切割。

时间复杂度 $\mathcal{O}(Qn)$

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
namespace FastIO
{
    #define gc() readchar()
    #define pc(a) putchar(a)
    #define SIZ (int)(1e6+15)
    char buf1[SIZ],*p1,*p2;
    char readchar()
    {
        if(p1==p2)p1=buf1,p2=buf1+fread(buf1,1,SIZ,stdin);
        return p1==p2?EOF:*p1++;
    }
    template<typename T>void read(T &k)
    {
        char ch=gc();T x=0,f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=gc();}
        while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
        k=x*f;
    }
    template<typename T>void write(T k)
    {
        if(k<0){k=-k;pc('-');}
        static T stk[66];T top=0;
        do{stk[top++]=k%10,k/=10;}while(k);
        while(top){pc(stk[--top]+'0');}
    }
}using namespace FastIO;
#define N ((int)(1e5+15))

int n,k,ans,sz[N];
vector<int> g[N];
void dfs(int u,int f)
{
    sz[u] = 1;
    for(int v : g[u])
    {
        if(v == f) continue;
        dfs(v,u); sz[u] += sz[v];
    }
    if(sz[u] == k) ++ans, sz[u] = 0;
}
void solve()
{
    read(n); read(k); ans = 0;
    for(int i=1; i<=n; i++) { sz[i] = 0; g[i].clear(); }
    for(int i=1,u,v; i<n; i++)
    {
        read(u); read(v);
        g[u].push_back(v); g[v].push_back(u);
    }
    if(n % k != 0) return  puts("NO"),void(0); 
    dfs(1,1); puts(((ans == n/k) ? ("YES") : ("NO")));
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    int Q; read(Q); while(Q--) solve();
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录