Tree 2017icpc沈阳沈阳站

Problem Description
Consider a un-rooted tree T which is not the biological significance of tree or plant, but a tree as an undirected graph in graph theory with n nodes, labelled from 1 to n. If you cannot understand the concept of a tree here, please omit this problem.
Now we decide to colour its nodes with k distinct colours, labelled from 1 to k. Then for each colour i = 1, 2, · · · , k, define Ei as the minimum subset of edges connecting all nodes coloured by i. If there is no node of the tree coloured by a specified colour i, Ei will be empty.
Try to decide a colour scheme to maximize the size of E1 ∩ E2 · · · ∩ Ek, and output its size.

Input
The first line of input contains an integer T (1 ≤ T ≤ 1000), indicating the total number of test cases.
For each case, the first line contains two positive integers n which is the size of the tree and k (k ≤ 500) which is the number of colours. Each of the following n - 1 lines contains two integers x and y describing an edge between them. We are sure that the given graph is a tree.
The summation of n in input is smaller than or equal to 200000.

Output
For each test case, output the maximum size of E1 ∩ E1 … ∩ Ek.

Sample Input

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

Sample Output

1
0
1

题意: 一个有n个节点的树,现在给你k种颜色,让你给每个节点染色(方案自己选),定义Ei为连接第i种颜色的所有节点的边的最小集合(类似于最下生成树)
定义ans=所有E取交集的大小, 要你求出ans的最大值。

对于我来说 题目实在难懂,看了好久。
看懂之后其实很简单。 考虑每条边的贡献 对于每条边链接的两颗子树,如果这两颗子树的大小都大于等于k 那么这条边就是有贡献的。
ans++;
dfs一遍即可

#include<bits/stdc++.h>
#define LL long long
#define N 100010
using namespace std;
const int MAX=1e6+10;
const int matX = 1e2 + 5;
const int mod = 1e9 + 7;
class edge {
public:
    int u,v,next;
};
edge ed[MAX<<1];
int head[MAX];
int tot;
void add(int u,int v) {
    ed[tot].u=u;
    ed[tot].v=v;
    ed[tot].next=head[u];
    head[u]=tot;
    tot++;
}
void init() {
    tot=0;
    memset(head,-1,sizeof head);
}
int sizes[MAX];
int ans=0;
int n,k;
void dfs(int u,int per) {
    sizes[u]=1;
    //cout<<u<<"<-"<<per<<endl;
    for(int i=head[u]; i!=-1; i=ed[i].next) {
        int v=ed[i].v;
        if(v==per) continue;
        dfs(v,u);
        sizes[u]+=sizes[v];
    }
    if(sizes[u]>=k && n-sizes[u]>=k) ans++;
}
int main() {
    int T;
    scanf("%d",&T);
    while(T--) {
        init();
        memset(sizes,0,sizeof sizes);
        ans=0;
        scanf("%d %d",&n,&k);
        for(int i=1; i<n; i++) {
            int u,v;
            scanf("%d %d",&u,&v);
            add(u,v);
            add(v,u);
        }
        dfs(1,-1);
        cout<<ans<<endl;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值