cf1088E Ehab and a component choosing problem (树形dp)

时间:2023-03-09 22:01:40
cf1088E Ehab and a component choosing problem (树形dp)

题意(考试时看错了对着样例wa了好久..):从树上选k个连通块,使得权值的平均值最大的基础上,选的块数最多

如果不考虑块数最多的限制,肯定是只选一个权值最大的块是最好的

然后只要看这个权值最大的块有多少个不相交的就可以了

做法就是,在dp的时候,一旦找到了和最大权值相等的块,直接统计答案,然后把这一块的权值改成-inf

 #include<bits/stdc++.h>
#define pa pair<int,int>
#define CLR(a,x) memset(a,x,sizeof(a))
#define MP make_pair
using namespace std;
typedef long long ll;
const int maxn=3e5+; inline char gc(){
return getchar();
static const int maxs=<<;static char buf[maxs],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,maxs,stdin),p1==p2)?EOF:*p1++;
}
inline ll rd(){
ll x=;char c=gc();bool neg=;
while(c<''||c>''){if(c=='-') neg=;c=gc();}
while(c>=''&&c<='') x=(x<<)+(x<<)+c-'',c=gc();
return neg?(~x+):x;
} int N,a[maxn];
int eg[maxn*][],egh[maxn],ect;
ll f[maxn],answ=-1e15,ansk; inline void adeg(int a,int b){
eg[++ect][]=b,eg[ect][]=egh[a],egh[a]=ect;
} inline void dfs1(int x,int fa){
f[x]=a[x];
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(b==fa) continue;
dfs1(b,x);
if(f[b]>) f[x]+=f[b];
}
answ=max(answ,f[x]);
}
inline void dfs2(int x,int fa){
f[x]=a[x];
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(b==fa) continue;
dfs2(b,x);
if(f[b]>) f[x]+=f[b];
}
if(f[x]==answ) ansk++,f[x]=-1e15;
} int main(){
//freopen("","r",stdin);
int i,j,k;
N=rd();
for(i=;i<=N;i++) a[i]=rd();
for(i=;i<N;i++){
int a=rd(),b=rd();
adeg(a,b);adeg(b,a);
}
dfs1(,);dfs2(,);
answ*=ansk;
printf("%I64d %I64d\n",answ,ansk);
return ;
}