21.6.13 t3
tag:树形dp
\(n^3\) 暴力,设 \(f_{i,j}\) 表示 \(i\) 的关键点为 \(j\)。
转移时枚举 \(x\) 的关键点和 \(son\) 的关键点,转移条件即为满足关键点的性质(关键点为所有源点中离它最近的)
- \(dis(x,p_x)\le dis(x,p_{son})\)
- \(dis(son,p_{son})\le dis(son,p_{son})\)
然后如果按 \(dis_x\) 从大到小排序,就变成了一个单点修改,求前缀 \(min\) 的问题(对于按 \(dis_{son}\) 从小到大的排列来说)
复杂度 \(O(n^2logn)\),可以用BIT。
#include<bits/stdc++.h>
using namespace std;
template<typename T>
inline void Read(T &n){
char ch; bool flag=false;
while(!isdigit(ch=getchar()))if(ch=='-')flag=true;
for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48));
if(flag)n=-n;
}
enum{
MAXN = 1005
};
int f[MAXN][MAXN], n, t[MAXN], a[MAXN];
struct _{
int nxt, to;
_(int nxt=0, int to=0):nxt(nxt),to(to){}
}edge[MAXN<<1];
int fst[MAXN], tot;
inline void Add_Edge(int f, int t){
edge[++tot] = _(fst[f], t); fst[f] = tot;
edge[++tot] = _(fst[t], f); fst[t] = tot;
}
int dis[MAXN][MAXN], rt;
void getdis(int x, int y){
for(register int u=fst[x]; u; u=edge[u].nxt){
int v=edge[u].to;
if(v==y) continue;
dis[rt][v] = dis[rt][x]+1;
getdis(v,x);
}
}
namespace BIT{
#define lowbit(x) (x&-x)
int t[MAXN];
inline void Add(int x, int k){for(;x<=n;x+=lowbit(x))t[x]=min(t[x],k);}
inline int Query(int x){int res=INT_MAX;for(;x;x-=lowbit(x))res=min(res,t[x]);return res;}
#undef lowbit
}
using BIT::Add;
using BIT::Query;
int p[MAXN][MAXN], now, loc[MAXN][MAXN], mxr[MAXN][MAXN];
inline bool cmp(const int &u, const int &v){
return dis[now][u]<dis[now][v];
}
void dp(int x, int y){
for(register int i=1; i<=n; i++) f[x][i] = t[dis[x][i]]; f[x][x] = a[x];
for(register int u=fst[x]; u; u=edge[u].nxt){
int v=edge[u].to;
if(v==y) continue;
dp(v,x);
// for(register int i=1; i<=n; i++){
// int res=INT_MAX;
// for(register int j=1; j<=n; j++)
// if(dis[x][j]>=dis[x][i] and dis[v][i]>=dis[v][j])
// res = min(res,f[v][j]);
// f[x][i] += res;
// printf("(%d %d %d) %d\n",x,i,v,res);
// }
for(register int i=1; i<=n; i++) BIT::t[i] = INT_MAX;
for(register int r=n, l; r; r=l-1){
l=r; while(l>1 and dis[x][p[x][l]]==dis[x][p[x][l-1]]) Add(loc[v][p[x][l]],f[v][p[x][l]]), l--;
Add(loc[v][p[x][l]],f[v][p[x][l]]);
for(register int j=l; j<=r; j++) f[x][p[x][j]] += Query(mxr[v][dis[v][p[x][j]]]);
}
}
}
int main(){
// freopen("3.in","r",stdin);
// freopen("33.out","w",stdout);
Read(n);
for(register int i=1; i<=n; i++) Read(a[i]);
for(register int i=1; i<=n; i++) Read(t[i]);
for(register int i=1; i<n; i++){
int u, v;
Read(u); Read(v);
Add_Edge(u,v);
}
for(rt=1; rt<=n; rt++) getdis(rt,0);
for(register int i=1; i<=n; i++){
for(register int j=1; j<=n; j++) p[i][j] = j;
now = i; sort(p[i]+1,p[i]+n+1,cmp);
for(register int j=1; j<=n; j++) loc[i][p[i][j]] = j, mxr[i][dis[i][p[i][j]]] = j;
}
dp(1,0);
int ans=INT_MAX;
for(register int i=1; i<=n; i++) ans = min(ans,f[1][i]);
cout<<ans<<'\n';
return 0;
}