U74201 旅行計劃 樹上找鏈長度

題目背景

珂朵莉放假了,她打算去唐山旅行。html

題目描述

咱們簡單地把唐山的共 nn 個景點當作是一棵樹,有 n-1n1 條邊將它們鏈接起來,每一個景點有一個遊覽指數 v_ivi。珂朵莉的假期時間不長,她只打算參觀連續的剛好 kk 個景點。珂朵莉很可愛,因此她但願她所參觀的景點裏遊覽指數最低的景點的遊覽指數最高,她如今想知道其最高值是多少。spa

輸入輸出格式

輸入格式:code

第一行兩個整數 n,khtm

接下來共 n1 行每行兩個整數 b ,表示這兩個景點相連blog

接下來 n 個整數 vi
string

輸出格式:it

一個整數,如題描述io

輸入輸出樣例

輸入樣例ast

4 2
1 2
1 3
2 4
1 2 4 3
輸出樣例
2

說明

對於百分之三十的數據class

n,k,v100

對於百分之六十的數據

n,k,v500

對於百分之百的數據

kn100000

1vi1000000

 

這道題用二分枚舉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;
}
相關文章
相關標籤/搜索