HDU 5242 上海大都会 G题

这道题其实是求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
",++icase,ans);
	}
	
	return 0;
}

  

原文地址:https://www.cnblogs.com/jie-dcai/p/4539820.html