【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;
}