目录
显示
题目链接
题解
一种显然的贪心想法是先完成子树大小最大的节点。
需要注意一个坑点:应该先把当天完成的所有节点全部 pop 掉后,再将接下来可以完成的任务 push 进去(否则会出现一天同时完成一个任务及其子任务的情况)。
其实按深度贪心也是正解。(但是两种贪心我都没法证明/kk)
#include <cstdio> #include <algorithm> #include <queue> #include <vector> using namespace std; struct edge { int v,next; }e[100005]; struct node { int x,siz; bool operator<(const node&a)const { return siz<a.siz; } }; int head[100005],cnt,siz[100005],topush[100005],num[100005]; priority_queue<node> q; vector<int> res[100005]; void addedge(int u,int v) { e[++cnt].v=v; e[cnt].next=head[u]; head[u]=cnt; } void dfs(int x) { siz[x]=1; for(int i=head[x];i;i=e[i].next) { dfs(e[i].v); siz[x]+=siz[e[i].v]; } } int main() { int n,m,ans=1; scanf("%d%d",&n,&m); for(int i=2;i<=n;i++) { int x; scanf("%d",&x); addedge(x,i); } dfs(1); q.push({1,n}); while(!q.empty()) { num[ans]=min((int)q.size(),m); int pushnum=0; for(int i=1;i<=num[ans];i++) { node u=q.top(); q.pop(); res[ans].push_back(u.x); for(int j=head[u.x];j;j=e[j].next) topush[++pushnum]=e[j].v; } for(int i=1;i<=pushnum;i++) q.push({topush[i],siz[topush[i]]}); ans++; } ans--; printf("%d\n",ans); for(int i=1;i<=ans;i++) { printf("%d ",num[i]); for(int j=0;j<num[i];j++) printf("%d ",res[i][j]); puts(""); } return 0; }