SCAU 19032 树上上升序列

Description

百度2020校招Java研发工程师笔试卷(第三批)

度度熊给定一棵树,树上的第i个节点有点权a[i]。请你找出一条最长的路径(u,v),使得从u沿着唯一路径走到v的途中,点权不断严格递增。

换句话说,设路径为(u,p1,p2,p3…pm,v),则需要满足a[u]<a[p1]<a[p2]<…<a[pm]<a[v]。输出最长满足条件的路径的长度。

输入格式

第一行树的节点个数n , 接下来一行n个数字,表示每个点的点权a[i]。1<=n<=100000,1<=a[i]<=n。

接下来n-1行,每行两个数u,v代表树上的点u和v存在一条边。1<=u,v<=n。

输出格式

一行一个数字表示答案,即最长的长度。

输入样例

5
3 4 5 4 5
1 2
1 3
2 4
2 5

输出样例

3

提示

样例解释,最长的路径为3,路径序列<1,2,5>。

分析:

由于要找到最长上升序列,则要形成有向图,且由小的点指向大的点。
依次用入度为0的点遍历邻接点,与拓扑排序类似。
动态规划的思想:
每次用一个点遍历邻接点时,该邻接点的权值若比较大,则该邻接点的上升序列长度值为 已有的值(初始为1,可能会被其他点增大为其他值)前继点的上升序列长度值+1 两者的最大值。

源码:

#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
vector<int> e[100005];  //数据量较大,采用vector动态数组
int a[100005],len[100005];
int main()
{
    int n,i;
    cin>>n;
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);  //点的权值
    int x,y;
    int d[n+1]={0};  //入度数的数组
    for(i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);  //x,y需要比较谁的值更大,才可以连接成有向图
        if(a[x]<a[y])  //x比y小,可以从x走到y
        {
            e[x].push_back(y);
            d[y]++;
        }
        else if(a[x]>a[y])  //y比x小,可以从y走到x
        {
            e[y].push_back(x);
            d[x]++;
        }
        else  //相等时,由于不能构成上升序列,则不形成边
            continue;
    }
    for(i=1;i<=n;i++)
        len[i]=1;  //每个点的初始长度都为1
    int q[n+1],f=0,r=0;
    for(i=1;i<=n;i++)  //找到所有入度为0的点
        if(d[i]==0)
            q[r++]=i;
    while(f<r)
    {
        int t=q[f++];  //拿队头
        for(i=0;i<e[t].size();i++)  //每次用队头的点去遍历其邻接点
        {
            y=e[t][i];  //邻接点
            d[y]--;  //该点入度减一
            if(d[y]==0)  //如果入度变为0,则入队
                q[r++]=y;
            if(a[t]<a[y])  //更新y点的上升序列长度
                len[y]=max(len[y],len[t]+1);
        }
    }
    int ans=0;
    for(i=1;i<=n;i++)  //找到最大值,即为答案
        if(len[i]>ans)
            ans=len[i];
    cout<<ans<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值