暂无链接
艾奇摘苹果
【问题描述】
艾奇在遥远的美洲大陆有一片苹果树森林。
听上去非常不错的是,苹果森林每年收成都还不错。
艾奇摘苹果的方式非常有趣,由于苹果树太高,她常直接折断树枝来获得一大堆(整棵子树)的苹果。
艾奇也不想把苹果树破坏的太狠,毕竟苹果树也不是只结一年的苹果。所以她对于一棵树,至多会折断一根树枝。
艾奇不像过去的某鲁姓大师,她并没有那个力气倒拔苹果树,因为一棵树的根是埋在土里的。所以她并不能获得整棵树的苹果。
众所周知,美洲大陆龙卷风贼多。龙卷风既然能摧毁停车场,那么吹翻一片苹果森林应该不是什么难事。所以艾奇养了一些小机器人给艾奇预警龙卷风。
艾奇把这些小机器人放在花上,这样一来小机器人就能吸收树的养分工作,但是这也导致了这朵花不能结果。
如果你折断了一根树枝,小机器人就会因为没有养分而狂躁,它们只吃原本和它们属于同一棵树上被摘下来的苹果。如果这些苹果不够吃,它们就会把艾奇吃掉。
树林有点大,艾奇想知道,照她这种收果实的方法,在自己不被吃掉的情况下,至多能收获多少苹果呢?
【输入格式】
输入文件名为
a
p
p
l
e
.
i
n
apple. in
apple.in。
第一行两个整数
n
m
n\ m
n m分别表示这片森林的节点树和树枝数量(就是边的数量)。我们默认一棵树的根就是这棵树中编号最小的节点。
接下来
n
n
n个整数。
如果该整数为正,那么表示这个节点结苹果的数量。
如果该整数为负,那么表示这个节点养了一个小机器人,它被摘下来要吃的
果子数量。
对于一棵树的根节点,这个节点的权值可以忽略。
接下来
m
m
m行,每行两个整数
i
,
j
i,j
i,j表示
i
i
i和
j
j
j在树上有边相连。
【输出格式】
输出文件名为
a
p
p
l
e
.
o
u
t
apple.out
apple.out。
一行一个整数,表示艾奇至多能收获多少苹果。
【输入样例 1】
详见 a p p l e 1. i n apple1.in apple1.in
【输出样例 1】
详见 a p p l e 1. o u t apple1.out apple1.out
【数据范围】
题解
d f s dfs 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();}