这道题其实是求K条最长的不重叠的链。贪心算法+DFS即可求。深度优先搜索时,返回当前子树的最长链,使用优先队列保存其他孩子结点的最长链,即可。求结果时只需从优先队列中取前K个值的和。这相当于暴力删除每条最长的链。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define LL long long using namespace std; const int N=100050; int head[N],indegree[N],val[N]; struct Edge{ int u,v; int next; }edge[N]; int n,k,tot,r; priority_queue<LL>que; void addedge(int u,int v){ edge[tot].u=u; edge[tot].v=v; edge[tot].next=head[u]; head[u]=tot++; } int getRoot(){ for(int i=1;i<=n;i++){ if(indegree[i]==0) return i; } } LL dfs(int rt){ LL maxval=0; for(int e=head[rt];e!=-1;e=edge[e].next){ int v=edge[e].v; LL val=dfs(v); if(val>maxval){ if(maxval!=0) que.push(maxval); maxval=val; } else que.push(val); } return maxval+val[rt]; } int main(){ int T,u,v,icase=0; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++){ scanf("%d",&val[i]); head[i]=-1; indegree[i]=0; } tot=0; for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); indegree[v]++; addedge(u,v); } // r=getRoot(); while(!que.empty()) que.pop(); LL ans=dfs(1); for(int i=2;i<=k&&!que.empty();i++){ ans+=que.top(); que.pop(); } printf("Case #%d: %I64d\n",++icase,ans); } return 0; }
时间: 2024-12-29 07:52:02