HDU - 6228 Tree

Tree
题 意:给你n个节点的一颗树,用k种颜色染色,求一个最小的边的Ei集合,Ei代表一个最小的边集连接所有节点颜色为i的集合。
数据范围:
1 &lt; = T &lt; = 1 e 4 1&lt;=T&lt;=1e4 1<=T<=1e4
1 &lt; = k &lt; = 500 1&lt;=k&lt;=500 1<=k<=500
n最多不超过 2 e 5 2e5 2e5
输入样例:

3
4 2
1 2
2 3
3 4
4 2
1 2
1 3
1 4
6 3
1 2
2 3
3 4
3 5
6 2

输出样例:

1
0
1

思维题树型题的套路:无根树先转化成有根树试一试,可能是每个节点的儿子节点个数,啥啥啥的。可以往这方面想一想。主要还是要去分析拉,看具体题目。边转化成点也是一个常用的套路

思 路:这就是一个思维题。先把无根树转化成有跟树,对于一个边,他只有两个情况,要不在最后的答案集合,要不不在,我们只考虑在最后的答案集合里面的。对于一条边在最后集合里面的,那么他一定被染色k次以上,我们可以对点染色,如果一个条边被染色k次以上,那么他两端的点也一定也被染色k次以上。
现在是一颗树,一个节点可以被染色至少k次以上,如果他的(包含他自己)子节点的个数sz[i]>=k个
并且如果n-sz[i]>=k就代表该节点和他父节点边可以被覆盖次数>=k次。所以这题就很简单了,只要dfs维护一下每个节点子节点个数就好了

如果有对你有帮助,点个赞哦~~O(∩_∩)O
如果有问题请留言哈!

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<queue>
#include<cmath>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<11
#define IN freopen("input.txt","r",stdin)
#define mst(x,y) memset(x,y,sizeof(x));
#define debug(x) cout<< #x <<" = "<< (x) <<endl;
#define min(x,y) x>y?y:x
#define max(x,y) x>y?x:y
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef unsigned long long ull;
const int mod = 1e6+3;
const int INF = 0x3f3f3f3f;
const int LINF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 2e5+5;
vector<int> G[maxn];
int sz[maxn];
int n,m;
void dfs(int s,int fa){
    sz[s] = 1;
    for(int i=0;i<G[s].size();i++){
        int to = G[s][i];
        if(to == fa)continue;
        dfs(to,s);
        sz[s]+=sz[to];
    }
}
int main() {
    //IN;
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d %d",&n,&m);
        for(int i=0;i<=n;i++) G[i].clear();
        mst(sz,0);
        for(int i=1;i<=n-1;i++){
            int u,v;
            scanf("%d %d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs(1,0);
        int ans = 0;
        for(int i=1;i<=n;i++){
            if(sz[i]>=m && n-sz[i]>=m)ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值