CodeForces - 1042F Leaf Sets
阿新 • • 發佈:2018-11-02
題面
題意
給出一棵樹,要求將其葉子分成幾個集合,要求每個集合中葉子兩兩之間的距離不大於k,求至少要將其分成幾個集合。
做法
因為n很大,所以考慮貪心。
首先dfs,我們可以自下而上逐個子樹考慮,對於一個子樹,可以將其拆成幾條鏈,可以將較短的幾條鏈合併在一起,而長的鏈獨自一個集合,然後其父節點與短鏈集合相連,這樣可以保證答案較優。
具體見程式碼,比較難描述。
程式碼
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include <algorithm>
#define N 1001000
using namespace std;
int n,m,first[N],bb,ds[N],ans;
struct Bn
{
int to,next;
}bn[N<<1];
inline void add(int u,int v)
{
bb++;
bn[bb].to=v;
bn[bb].next=first[u];
first[u]=bb;
}
int dfs(int now,int last)
{
if(ds[now]==1) return 0;
int i,j,p,q,t;
vector< int>use;
use.clear();
for(p=first[now];p!=-1;p=bn[p].next)
{
if(bn[p].to==last) continue;
use.push_back(dfs(bn[p].to,now)+1);
}
sort(use.begin(),use.end());
for(i=use.size()-1;i>=0;i--)
{
t=use[i];
if(i) t+=use[i-1];
if(t<=m) return use[i];
ans++;
}
return -N;
}
int main ()
{
memset(first,-1,sizeof(first));
int i,j,p,q;
cin>>n>>m;
for(i=1;i<n;i++)
{
scanf("%d%d",&p,&q);
add(p,q),add(q,p);
ds[p]++,ds[q]++;
}
for(i=1;i<=n;i++) if(ds[i]>1) break;
if(dfs(i,-1)>0) ans++;
cout<<ans;
}