题意为给我们一棵树
修复每个点需要费用
当一个点周围个点都被修复时,就会获得的收入,如果多个满足取最大值
问最大收入为多少
首先根据最大权闭合图模型
先把所有的收益全部加上去。之后计算最小割,使得对于每份收益,要么放弃要么支付对应的费用
答案转化为总收益-最小割
我们看n = 200非常小,直接floyd暴力一遍所有点的算法,矩阵存起来
然后开始建图,我们定义为对于i这个点,小于等于p距离的点全选
1.源点连向每个,容量为 代表增量收益
2,每个连接对应与i点距离为p的原图中的点,容量为INF
3,每个原图中的点连向 汇点,表示支付修复这个点的费用
4,每个连向来限制割边,必须先放弃p才能放弃p+1
建出来的图大概长这样
答案等于总收益减去最小割。
代码如下
#include <bits/stdc++.h>
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair<int,int>
#define et cout<<'\n'
#define xx first
#define yy second
using namespace std;
template <typename _Tp>void input(_Tp &x){
char ch(getchar());bool f(false);while(!isdigit(ch))f|=ch==45,ch=getchar();
x=ch&15,ch=getchar();while(isdigit(ch))x=x*10+(ch&15),ch=getchar();
if(f)x=-x;
}
template <typename _Tp,typename... Args>void input(_Tp &t,Args &...args){input(t);input(args...);}
int id[255][255], id1[255], dis[255][255], w[255], v[255];
int n;
const int N = 1e6+10, M = N*2,INF = 1e9+7;
int S, T;
int h[N], e[M], f[M], ne[M], idx;
int d[N], cur[N];
void add(int a, int b, int c)
{
e[idx] = b, f[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
e[idx] = a, f[idx] = 0, ne[idx] = h[b], h[b] = idx ++ ;
}
bool bfs()
{
queue<int> q;
memset(d, -1, sizeof d);
q.push(S);
d[S] = 0, cur[S] = h[S];
while (q.size())
{
auto t=q.front();
q.pop();
for (int i = h[t]; ~i; i = ne[i])
{
int ver = e[i];
if (d[ver] == -1 && f[i])
{
d[ver] = d[t] + 1;
cur[ver] = h[ver];
if (ver == T) return true;
q.push(ver);
}
}
}
return false;
}
int find(int u, int limit)
{
if (u == T) return limit;
int flow = 0;
for (int i = cur[u]; ~i && flow < limit; i = ne[i])
{
cur[u] = i; // 当前弧优化
int ver = e[i];
if (d[ver] == d[u] + 1 && f[i])
{
int t = find(ver, min(f[i], limit - flow));
if (!t) d[ver] = -1;
f[i] -= t, f[i ^ 1] += t, flow += t;
}
}
return flow;
}
int dinic()
{
int r = 0, flow;
while (bfs()) while (flow = find(S, INF)) r += flow;
return r;
}
signed main(){
memset(h,-1,sizeof h);
S=0;
input(n);
int cnt = 0, ans;
fer(i,1,n){
fer(j,1,n){
dis[i][j] = 0x3f3f3f3f;
}
}
fer(i,1,n){
input(w[i]);
dis[i][i] = 0;
}
fer(i,0,n-1){
input(v[i]);
}
ans = n*v[n - 1];
fer(i,1,n-1){
int u, v;
input(u,v);
dis[v][u]=dis[u][v]=1;
}
fer(k,1,n){
fer(i,1,n){
fer(j,1,n){
dis[i][j]=min(dis[i][j], dis[i][k] + dis[k][j]);
}
}
}
fer(i,1,n) id1[i]=++cnt;
fer(i,1,n){
fer(j,0,n-1){
id[i][j]=++cnt;
}
}
T=++cnt;
fer(i,1,n){
fer(j,0,n-1){
if(j==0){
add(S,id[i][j],v[j]);
}
else{
add(S,id[i][j],v[j]-v[j-1]);
}
if (j) {
add(id[i][j], id[i][j - 1],INF);
}
}
}
fer(i,1,n){
add(id1[i],T,w[i]);
}
fer(i,1,n){
fer(j,1,n){
int d=dis[i][j];
add(id[i][d],id1[j],INF);
}
}
cout << ans - dinic();
return 0;
}