欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-19 20:55:18
...

题目链接: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;
}