因爲是同步進行的,所以第i層的不會影響到i+1層,所以我們可以把他們分層處理,對於當前層數,一直往上走,但是分層後他們可能會在某個點匯聚,就是它們的lca,所以我們得把他們所有的lca給求出來,然後建另外一棵樹(虛樹),對這個樹dfs一遍求一下答案,求他們的lca,只要依次從左到右,兩兩的lca就是了,順序可通過dfs序從小到大排序,然後對於n個點他們的lca最多 只有n-1個,因爲假設求a b c3個點兩兩的lca, A = lca(a,b),那麼a、b與c的lca其實就可以通過A和c的lca來得到。所以最多n-1個,然後最主要就是建虛樹的過程,可以通過單調棧來建樹,對於第i層,把s壓入棧中,然後對於下一個點,求一遍與棧頂 元素top的lca,然後lca依次與top-1比較,直到lca的dfs大於top-1的dfs序的時候結束。因爲是 從左到右遍歷的點,所以正確性能保證。
部分細節見代碼
複雜度O(nlogn)
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);++i)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);--i)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
int n,s;
int a[man],rk[man];
vector<int>sp[man],h[man],x_sp[man];
int dep[man],fa[man][20],max_dep;
int cnt = 0;
void dfs(int u,int f){
rk[u] = ++cnt;
dep[u] = dep[f] + 1;
h[dep[u]].emplace_back(u);
max_dep = max(max_dep,dep[u]);
fa[u][0] = f;
for(int i = 1;i < 20;i++){
fa[u][i] = fa[fa[u][i-1]][i-1];
}
for(int i = 0;i < sp[u].size();i++){
int v = sp[u][i];
if(v==f)continue;
dfs(v,u);
}
}
int lca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
for(int i = 19;i >= 0;i--){
if(dep[fa[u][i]]>=dep[v]){
u = fa[u][i];
}
}
if(u==v)return v;
for(int i = 19;i >= 0;i--){
if(fa[u][i]!=fa[v][i]){//因爲u,v的祖先的祖先也是u,v的祖先
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][0];
}
int sta[man],top;
void insert(int u){
if(1==top){
sta[++top] = u;
return;
}
int fa = lca(sta[top],u);
while(top>=2&&rk[fa]<=rk[sta[top-1]]){
x_sp[sta[top-1]].emplace_back(sta[top]);
--top;
}
if(fa!=sta[top]){
x_sp[fa].emplace_back(sta[top]);
sta[top] = fa;
}
sta[++top] = u;
}
ll dp(int u,int f){
if(x_sp[u].size()==0){
return a[u];
}
ll ans = 0;
for(auto v:x_sp[u]){
if(v==f)continue;
ll tp = dp(v,u);
ans += tp>1 ? max(1ll,tp-(dep[v]-dep[u])) : tp;
}
x_sp[u].clear();
//printf("u:%d as:%lld\n",u,ans);
return ans ;
}
int main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
scanf("%d%d",&n,&s);
For(i,1,n){
scanf("%d",a+i);
}
For(i,1,n-1){
int u,v;
scanf("%d%d",&u,&v);
sp[u].emplace_back(v);
sp[v].emplace_back(u);
}
dfs(s,0);
ll ans = a[s]>1 ? a[s]-1:a[s];
For(i,2,max_dep){
sort(h[i].begin(),h[i].end(),[](const auto &a,const auto &b){return rk[a] < rk[b];});
top = 0;
sta[++top] = s;
x_sp[s].clear();
For(j,0,h[i].size()-1){
x_sp[h[i][j]].clear();
insert(h[i][j]);
}
while(top>1){
x_sp[sta[top-1]].emplace_back(sta[top]);
--top;
}
ll res = dp(s,0);
ans += res>1 ? max(1ll,res - 1) : res;
//printf("res:%d\n",res);
}
printf("%lld\n",ans);
return 0;
}