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

洛谷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 !
评论
  目录