2017ICPC沈阳赛现场赛 L-Tree (dfs)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6228
题目大意:给一棵树,需要用k种颜色给树上的节点染色,问你在最优的染色方案下,相同颜色的节点连接的最小边集的交集最大是多少?
解题思路:每一条边要么属于交集中,要么不属于交集中?关键在于如何判定每一条边到底是属于交集的集合还是不属于交集的集合。假设如果某条边左边的点数和右边的点数均大于等于k,那么这条边就一定属于交集中,因为我们可以对左边的点涂k中颜色,对右边的点也涂k种颜色,否则这条边便不属于交集中。那么问题转化为:求每条边左边的节点个数和右边节点的个数,如果两边节点的个数均大于k,则进行计数。
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=200005; int n,k; vector<int> mp[maxn]; int ans; int dfs(int u,int fa){ int size=mp[u].size(); int sum=1; for(int i=0;i<size;i++){ int v=mp[u][i]; if(v==fa)continue; sum+=dfs(v,u); } if(sum>=k&&(n-sum)>=k) ans++; return sum; } int main(){ int t; cin>>t; while(t--){ cin>>n>>k; for(int i=1;i<=n;i++)mp[i].clear(); ans=0; int u,v; for(int i=1;i<n;i++){ cin>>u>>v; mp[u].push_back(v); mp[v].push_back(u); } int lt=dfs(u,v); int rt=dfs(v,u); //cout<<lt<<" "<<rt<<endl; if(lt>=k&&rt>=k) ans--; //u-v边重复计数了一次 cout<<ans<<endl; } return 0; }