HDU 6228 Tree ACM/ICPC 2017 Shenyang(思维)

Tree

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 263    Accepted Submission(s): 178

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

Source

2017ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学)



        一道思维题。

        大致题意是,给你一棵树,让你把这些树上的节点用M种颜色染,然后问你在最优的染色方案下,相同颜色点连接的最小边集的交集最大是多少。题目可能有点难理解,看懂样例就知道了。

        初始想法就是,我至少要选择M个点对,这些点对的颜色相同,要求这些点对的路径交的数量最高。那么,如果是这样的话,我首先选取树的直径,直径两端的点即为第一个点对,然后依次往里面缩小,缩小一级之后,再往周围拓展。听不懂也不要担心,因为按照此贪心策略,会得到一个WA。因为我们的相同颜色连接不只是一条路径,而是可以有多条路径,计算时候也不单只是考虑一条路径。

        所以说我们换一个思路考虑。我们知道,在一棵树中,边是与点紧密连接的,而一条边要么属于最后答案所在的集合,要么不属于,那么我们要做的就是看看哪些边可以属于最后答案,哪些不属于。那么我们如何判定呢?我们从答案出发,答案的交集中的边的左右两端一定都包含M种颜色,不然肯定不是交集中的边。所以以此为判据,对于一条边,如果这条边的左右端的点数量都大于颜色的总数量,那么就说明这条边最后可以在最后结果中。统计满足条件的边数即可。具体见代码:

#include<bits/stdc++.h>
#define N 201000
#define LL long long

using namespace std;

vector<int> g[N];
int n,m,sz[N];

void getsize(int x,int fa)
{
    sz[x]=1;
    for(int i=0;i<g[x].size();i++)
    {
        int y=g[x][i];
        if (y==fa) continue;
        getsize(y,x); sz[x]+=sz[y];
    }
}

int main()
{
    int T_T;
    cin>>T_T;
    while(T_T--)
    {
        scanf("%d%d",&n,&m);
        memset(g,0,sizeof(g));
        for(int i=1;i<n;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
        int ans=0;
        getsize(1,0);
        for(int i=1;i<=n;i++)
            if (sz[i]>=m&&n-sz[i]>=m) ans++;
        printf("%d\n",ans);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值