2017 Shenyang onsite replay L - Tree

这里主要补一下L题,感觉也是挺巧妙的,不过也不难

传送门

题目大意:

给予一个无根树,然后给予K种颜色,求将所有颜色的点都连接起来,这K种颜色最多有多少条公共的边。

解题思路:
  • 首先看一个图,我们直接拆分边,如果这个边的两端都有>=k 个点,那么这条边就可以公共通过。

在这里插入图片描述

  • 假如K == 3, 那么如果我切割中间的边, 那么左右的点的数目都是 >= 3 ,就符合条件,所以我们根据这个性质来继续解题。
  • 因此我们只需要找一个点作为根即可。(找度为1的点,比较方便)
  • 然后我们记录每个点有多少个子节点,然后我们去遍历每个点,他的子节点 和 n - 子节点 ,判断这两个数值是否 >= k 即可,累加统计
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <unordered_map>
#include <stack>
#include <cmath>
#include <deque>

using namespace std;

typedef long long ll;

const int N = 200010, M = 400010;
const int mod = 1e9 + 7;

pair <int,int> ans[N];

int h[N], e[M], ne[M], idx; 
int d[N];
int b[N];

int num = 1;

void add(int x, int y){
	e[idx] = y, ne[idx] = h[x], h[x] = idx ++;
}

void dfs(int u, int f){
	b[u] = 1;
	for (int i = h[u]; i != -1; i = ne[i]){
		int j = e[i];
		if (j != f){
			dfs(j,u);
		}
	}
	if (f != -1) b[f] += b[u];
}

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
    	idx = 0;
    	memset(d,0,sizeof d);
    	memset(h,-1,sizeof h);
    	int n, k;
    	scanf("%d%d",&n,&k);
    	for (int i = 1; i <= n - 1; i ++){
    		int x, y;
    		scanf("%d%d",&x,&y);
    		ans[i] = {x,y};
    		d[x] ++, d[y] ++;
    		add(x,y), add(y, x);
    	}
    	int res = 0;
    	int x;
    	for (int i = 1; i <= n; i++){
    		if (d[i] == 1){
    			x = i;
    		}
    	}
    	dfs(x, -1);

    	for (int i = 1; i <= n; i++){
    		if (b[i] >= k && n - b[i] >= k) res ++;
    	}
    	printf("%d\n",res);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值