[2018.10.18 T1] 艾奇摘苹果

版权声明:大佬您能赏脸,蒟蒻倍感荣幸,还请联系我让我好好膜拜。 https://blog.csdn.net/ShadyPi/article/details/83151428

暂无链接

艾奇摘苹果

【问题描述】

艾奇在遥远的美洲大陆有一片苹果树森林。
听上去非常不错的是,苹果森林每年收成都还不错。
艾奇摘苹果的方式非常有趣,由于苹果树太高,她常直接折断树枝来获得一大堆(整棵子树)的苹果。
艾奇也不想把苹果树破坏的太狠,毕竟苹果树也不是只结一年的苹果。所以她对于一棵树,至多会折断一根树枝。
艾奇不像过去的某鲁姓大师,她并没有那个力气倒拔苹果树,因为一棵树的根是埋在土里的。所以她并不能获得整棵树的苹果。
众所周知,美洲大陆龙卷风贼多。龙卷风既然能摧毁停车场,那么吹翻一片苹果森林应该不是什么难事。所以艾奇养了一些小机器人给艾奇预警龙卷风。
艾奇把这些小机器人放在花上,这样一来小机器人就能吸收树的养分工作,但是这也导致了这朵花不能结果。
如果你折断了一根树枝,小机器人就会因为没有养分而狂躁,它们只吃原本和它们属于同一棵树上被摘下来的苹果。如果这些苹果不够吃,它们就会把艾奇吃掉。
树林有点大,艾奇想知道,照她这种收果实的方法,在自己不被吃掉的情况下,至多能收获多少苹果呢?

【输入格式】

输入文件名为 a p p l e . i n apple. in
第一行两个整数 n   m n\ m 分别表示这片森林的节点树和树枝数量(就是边的数量)。我们默认一棵树的根就是这棵树中编号最小的节点。
接下来 n n 个整数。
如果该整数为正,那么表示这个节点结苹果的数量。
如果该整数为负,那么表示这个节点养了一个小机器人,它被摘下来要吃的
果子数量。
对于一棵树的根节点,这个节点的权值可以忽略。
接下来 m m 行,每行两个整数 i , j i,j 表示 i i j j 在树上有边相连。

【输出格式】

输出文件名为 a p p l e . o u t apple.out
一行一个整数,表示艾奇至多能收获多少苹果。

【输入样例 1】

详见 a p p l e 1. i n apple1.in

【输出样例 1】

详见 a p p l e 1. o u t apple1.out

【数据范围】

TIM截图20181018190604.png

题解

d f s dfs 求一棵树中的最大子树,把所有树的最大子树加到一起。

代码

略微卡常

#include<bits/stdc++.h>
using namespace std;
const int M=1e6+5;
int val[M],vis[M],head[M],nxt[M<<1],to[M<<1],n,m,cnt,r,f;
long long ans,sum[M],mx;
char c;
void add(int f,int t){nxt[++cnt]=head[f],head[f]=cnt,to[cnt]=t;}
int read()
{
	for(r=0,f=1;!isdigit(c);c=getchar())if(c=='-')f=-1;
	for(;isdigit(c);c=getchar())r=(r<<1)+(r<<3)+c-'0';
	return r*f;
}
void dfs(int v){vis[v]=1,sum[v]=val[v];for(int i=head[v];i;i=nxt[i])if(!vis[to[i]])dfs(to[i]),sum[v]+=sum[to[i]],mx=max(mx,sum[to[i]]);}
void in()
{
	n=read(),m=read();
	for(int i=1;i<=n;++i)val[i]=read();
	for(int i=1,a,b;i<=m;++i)a=read(),b=read(),add(a,b),add(b,a);
}
void ac(){for(int i=1;i<=n;++i)if(!vis[i])mx=0,dfs(i),ans+=mx;printf("%lld",ans);}
int main(){in(),ac();}

猜你喜欢

转载自blog.csdn.net/ShadyPi/article/details/83151428
t1