珂朵莉放假了,她打算去唐山旅行。html
咱們簡單地把唐山的共 nn 個景點當作是一棵樹,有 n-1n−1 條邊將它們鏈接起來,每一個景點有一個遊覽指數 v_ivi。珂朵莉的假期時間不長,她只打算參觀連續的剛好 kk 個景點。珂朵莉很可愛,因此她但願她所參觀的景點裏遊覽指數最低的景點的遊覽指數最高,她如今想知道其最高值是多少。spa
輸入格式:code
第一行兩個整數 n,khtm
接下來共 n−1 行每行兩個整數 a b ,表示這兩個景點相連blog
接下來 n 個整數 vi
string
輸出格式:it
一個整數,如題描述io
輸入樣例ast
4 2 1 2 1 3 2 4 1 2 4 3
輸出樣例
2
對於百分之三十的數據class
n,k,v≤100
對於百分之六十的數據
n,k,v≤500
對於百分之百的數據
k≤n≤100000
1≤vi≤1000000
這道題用二分枚舉k上最小的最大值
而後check()判斷樹上是否有一條符合條件的鏈長度>=k;
用fir記錄當前節點兒子中最長鏈長度,sec爲當前節點兒子中第二長鏈,g[]爲第一加第二+1等於當前節點爲根節點時知足條件的最長鏈的長度(前提是當前節點知足條件)。
思想就是這樣;
代碼:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=100050; int pre[2*maxn],last[maxn],other[2*maxn],l; int n,k,val[maxn],ans,mid,qw; int fir[maxn],sec[maxn],g[maxn]; void add(int x,int y) { l++; pre[l]=last[x]; last[x]=l; other[l]=y; } void dfs(int u,int fa) { for(int p=last[u];p;p=pre[p]) { int v=other[p]; if(v==fa) continue; dfs(v,u); if(g[v]>fir[u])//兒子的最長鏈更新 當前節點的第一大鏈 { fir[u]=g[v]; } else if(sec[u]<g[v])//否則看看第二長鏈 { sec[u]=g[v]; } } if(val[u]>=mid&&sec[u]+fir[u]+1>=k) { qw=1; } if(val[u]>=mid) g[u]=fir[u]+1;//更新當前節點最長鏈 else g[u]=0; } int check() { qw=0; memset(g,0,sizeof(g)); memset(fir,0,sizeof(fir)); memset(sec,0,sizeof(sec)); dfs(1,0); return qw; } int main() { scanf("%d%d",&n,&k); for(int i=1;i<n;i++) { int a,b; scanf("%d%d",&a,&b); add(a,b); add(b,a); } for(int i=1;i<=n;i++) { scanf("%d",&val[i]); } int l=0,r=100001; while(l<=r) { mid=(l+r)>>1; if(check()) { ans=mid; l=mid+1; } else r=mid-1; } printf("%d",ans); return 0; }