【HDU6228】【2017ACM/ICPC亚洲区沈阳站】Tree

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6228

                                      Tree

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

 

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种颜料,给树的节点涂色。若有某两点涂成同一颜色i,则这两点之间的所有边都在集合Ei(边集)中,求所有集合的交集的最大值。

思路:对于一条边来说,如果它在交集中,那么这条边的两侧必须具有k种颜色,所以解题关键在于统计边两边的节点数。dfs遍历所有节点,统计该节点的子树所具有的节点数(包括它自己),再用总结点数减去子树节点数,如果二者都大于等于k,那么ans++。

这道题思路清晰了,代码就很简单了。

#include <iostream>
#include <vector>

using namespace std;

int n,k,ans;
vector<int>arc[200002];

int dfs(int u,int fa)
{
    int i,num=1;
    for(i=0;i<(int)arc[u].size();i++)
    {
        if(arc[u][i]==fa) continue; //不能是父节点
        num+=dfs(arc[u][i],u);
    }
    if(num>=k&&(n-num)>=k) ans++; //边的两边节点数大于等于k
    return num;
}
int main()
{
    int t,x,y,i;
    cin>>t;
    while(t--)
    {
        cin>>n>>k;
        ans=0;
        for(i=0;i<=n;i++)
        {
            arc[i].clear();
        }
        for(i=1;i<n;i++)
        {
            cin>>x>>y;
            arc[y].push_back(x);
            arc[x].push_back(y);
        }
        dfs(1,-1);//假设1是根节点,其父节点不存在设为-1
        cout<<ans<<endl;
    }
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值