罓风猪会
这只猪会做但是没开,哭了。
将问题放到最大权独立集上考虑,记
容易发现钦定权值只可能是正无穷或负无穷,也就是钦定一个点必选或不选。
记钦定的点为
若
若
考虑一个儿子
所以可以 DP,设
注意到没有必要每次枚举根做 DP,直接换根即可做到
这里贴下代码:
#include<bits/stdc++.h>
#define pb push_back
#define int long long
using namespace std;
const int N=1e6+5;
int T,n,a[N],f[N][2],g[N],ans;
vector<int> e[N];
void dfs(int x,int fa){
g[x]=1;
f[x][0]=0,f[x][1]=a[x];
for(auto v:e[x]){
if(v==fa) continue;
dfs(v,x);
g[x]+=(f[v][0]<f[v][1])*g[v];
f[x][0]+=max(f[v][0],f[v][1]);
f[x][1]+=f[v][0];
}
if(f[x][0]>f[x][1]) ans=max(ans,g[x]);
}
void dfs1(int x,int fa){
if(f[x][0]>f[x][1]) ans=max(ans,g[x]);
for(auto v:e[x]){
if(v==fa) continue;
int X0=f[x][0],X1=f[x][1],V0=f[v][0],V1=f[v][1],GX=g[x],GV=g[v];
f[x][1]-=V0,f[x][0]-=max(V0,V1);
g[x]-=(V0<V1)*GV;
f[v][1]+=f[x][0],f[v][0]+=max(f[x][0],f[x][1]);
g[v]+=(f[x][0]<f[x][1])*g[x];
dfs1(v,x);
f[x][0]=X0,f[x][1]=X1,f[v][0]=V0,f[v][1]=V1;
g[x]=GX,g[v]=GV;
}
}
void work(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],e[i].clear();
ans=0;
for(int i=1,u,v;i<n;i++){
cin>>u>>v;
e[u].pb(v),e[v].pb(u);
}
dfs(1,0);
dfs1(1,0);
cout<<ans<<'\n';
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>T;
while(T--) work();
return 0;
}
好了题解结束,谢谢观看。