标签:ret div 贪心 sub pac mes 16px tin span
题意:给定一棵树,选择l条路径覆盖最多的点的个数是多少。
(n <= 1e6)
题解:首先根据数据范围,得知时间复杂度O(n)。
满足一个贪心,即从叶子节点取最优,每次取路径最长的两个点。
用拓扑排序得到每个深度点数,显然这一层要么取l*2个点,要么全部去完。
(好妙啊)
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,k,In[1000010],dep[1000010],tot[1000010],ans=0; 4 int cnt=0,hed[1000010],to[2000010],nxt[2000010]; 5 bool vis[1000010]; 6 int q[1000010],f=1,e=0; 7 8 inline void add(int x,int y) { to[++cnt]=y,nxt[cnt]=hed[x],hed[x]=cnt; } 9 inline int Min(int x,int y) { return x<y? x:y; } 10 int main() { 11 scanf("%d%d",&n,&k); 12 for(int i=1,x,y;i<n;i++) 13 scanf("%d%d",&x,&y),add(x,y),add(y,x),++In[x],++In[y]; 14 for(int i=1;i<=n;i++) 15 if(In[i]==1) vis[i]=1,q[++e]=i,++tot[dep[i]=1]; 16 while(f<=e) { 17 int u=q[f++]; 18 for(int i=hed[u];i;i=nxt[i]) { 19 if(vis[to[i]]) continue; 20 if((--In[to[i]])==1) 21 vis[to[i]]=1,++tot[dep[to[i]]=dep[u]+1],q[++e]=to[i]; 22 } 23 } 24 for(int i=1;tot[i];i++) ans+=Min(k*2,tot[i]); 25 printf("%d\n",ans); 26 return 0; 27 }
标签:ret div 贪心 sub pac mes 16px tin span
原文地址:https://www.cnblogs.com/daniel14311531/p/10163969.html