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\n",++icase,ans);
	}

	return 0;
}

  

时间: 2024-12-29 07:52:02

HDU 5242 上海大都会 G题的相关文章

HDU 5241 上海大都会 F题

留意到,每一种语言的情况其实是独立的,也就是说,每一种语言的集合的包含的情况都是符合要求的.一种语言在图上可以有32种情况(由数据2知),所以,总的数就是32^n import java.util.*; import java.math.*; public class Main { static public void main(String []args){ Scanner scan=new Scanner(System.in); int T,icase=0; T=scan.nextInt()

HDU 5245 上海大都会 J题 (概率期望)

这道题的概率可以单独考虑每个格子对期望的贡献值.因为其实每个格子是否被选都可以认为是独立的,单独一个格子贡献的期望为1*(该格子K次被选的概率),所以答案其实就是每个格子K次被选中的概率之和. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define LL long long using namespace std; int main(){ LL

HDU 5239 上海大都会 D题(线段树+数论)

打表,发现规律是存在一定次数(较小)后,会出现a=(a*a)%p.可以明显地发现本题与线段树有关.设置标记flag,记录本段内的数是否均已a=a*a%p.若是,则不需更新,否则更新有叶子结点,再pushup. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define LL unsigned long long using namespace st

HDU 5242 GAME 2015上海邀请赛G题

题目链接:hdu 5242 题意:给定一颗以1号节点为根节点的有向树,每个节点有一个权值,问从1号节点出发k次,能到达的所有节点的和的最大值. 思路:贪心的把树的链按照权值和从大到小剖分成若干条链(过程可以根据上交书上的熟练剖分模版做细小改动),然后根据每条链的权值排序取最大的k个就是答案. 代码: #include <cstdio> #include <cmath> #include <iostream> #include <cstring> #inclu

HDU 5863 cjj&#39;s string game ( 16年多校10 G 题、矩阵快速幂优化线性递推DP )

题目链接 题意 : 有种不同的字符,每种字符有无限个,要求用这k种字符构造两个长度为n的字符串a和b,使得a串和b串的最长公共部分长度恰为m,问方案数 分析 : 直觉是DP 不过当时看到 n 很大.但是 m 很小的时候 发现此题DP并不合适.于是想可能是某种组合数学的问题可以直接公式算 看到题解的我.恍然大悟.对于这种数据.可以考虑一下矩阵快速幂优化的DP 首先要想到线性递推的 DP 式子 最直观的想法就是 dp[i][j] = 到第 i 个位置为止.前面最长匹配长度为 j 的方案数 但是如果仔

2017Summmer_上海金马五校 F题,G题,I题,K题

以下题目均自己搜 F题  A序列 一开始真的没懂题目什么意思,还以为是要连续的子串,结果发现时序列,简直智障,知道题意之后,好久没搞LIS,有点忘了,复习一波以后,直接双向LIS,处理处两个数组L和R,然后对整个数组扫一遍对于每一个下标取m=min(L[i],R[i]);用ans取2*m-1中的最大值.LIS用nlogn的算法实现,二分用的是lower_bound(),直接看代码. //Author: xiaowuga #include <bits/stdc++.h> #define maxx

2018 ACM 国际大学生程序设计竞赛上海大都会赛

传送门:2018 ACM 国际大学生程序设计竞赛上海大都会赛 2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛2018-08-05 12:00:00 至 2018-08-05 17:00:00时长: 5小时 比赛情况 实录 难度差不多介于省赛和区域赛之间吧.开题A是计算几何,有点思路后就先放下去写签到题,B读错题WA一发,K直接套模板,然后就接着看A.之前写过类似题,没注意数据范围就头铁地交了发n3的代码,TE后才发现数据范围是之前那道十多倍,就听学长的先看D.推十分钟公式无果后打算直

POJ 3528 hdu 3662 三维凸包模板题

POJ 3528题:http://poj.org/problem?id=3528 HDU 3662:http://acm.hdu.edu.cn/showproblem.php?pid=3662 一个是求三维凸包面数,一个是求三维凸包表面积,都是很裸的. 贴代码: #include<stdio.h> #include<algorithm> #include<string.h> #include<math.h> #include<stdlib.h>

2018 ACM 国际大学生程序设计竞赛上海大都会部分题解

题目链接 2018 ACM 国际大学生程序设计竞赛上海大都会 下午午休起床被同学叫去打比赛233 然后已经过了2.5h了 先挑过得多的做了 .... A题 rand x*n 次点,每次judge一个点位端点的共线向量数判断是否大于给定x 强行rand 500次 代码 #include<bits/stdc++.h> using namespace std; inline int read() { int x = 0,f = 1; char c = getchar(); while(c <