#1676 : 树上的等差数列(树形dp)

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

给定一棵包含N个节点的无根树,节点编号1~N。其中每个节点都具有一个权值,第i个节点的权值是Ai。  

小Hi希望你能找到树上的一条最长路径,满足沿着路径经过的节点的权值序列恰好构成等差数列。

输入

第一行包含一个整数N。  

第二行包含N个整数A1, A2, ... AN。  

以下N-1行,每行包含两个整数U和V,代表节点U和V之间有一条边相连。  

对于50%的数据,1 ≤ N ≤ 1000  

对于100%的数据,1 ≤ N ≤ 100000, 0 ≤ Ai ≤ 100000, 1 ≤ U, V ≤ N

输出

最长等差数列路径的长度

样例输入

7  
3 2 4 5 6 7 5  
1 2  
1 3  
2 7  
3 4  
3 5  
3 6

样例输出

4

思路:这道题我感觉很好。

总体思路是这样的,要找最长的等差数列,那么把d[i][j]当做是以i为节点,差为|d|的最长的长度,

那么这个节点两边就是要一边是+d,一边是-d,(自行想象)。

易错点就在于如果d=0时,那么就要考虑怎样找差值最大的两边的。这道题中用了f[i][0]和f[i][1]表示以i为节点的左端右端(不定)每次都从中找最长的进行保存,然后加起来。注意还要加上自身。

代码:

#include<iostream>
#include<string.h>
#include<map>
#include<vector>
#include<stdio.h>
using namespace std;
map<int,int>d[100100];
int vis[100100];
int w[100100];
int f[100100][2];
vector<int>G[100100];
int ans;
void dfs(int x)
{
    vis[x]=1;
    for(int i=0;i<G[x].size();i++)
    {
        int v=G[x][i];
        if(vis[v])
            continue;

        dfs(v);
        if(w[x]==w[v])
        {
            if(f[x][0]<f[x][1])
                f[x][0]=max(f[x][0],max(f[v][0],f[v][1])+1);
            else
                f[x][1]=max(f[x][1],max(f[v][0],f[v][1])+1);
            ans=max(ans,f[x][0]+f[x][1]+1);
        }
        else{
            d[x][w[x]-w[v]]=max(d[x][w[x]-w[v]],d[v][w[x]-w[v]]+1);//x节点,公差为w[x]-w[v]
            ans=max(ans,d[x][w[x]-w[v]]+d[x][w[v]-w[x]]+1);
        }
    }
}
int main()
{
    int n,u,v;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        G[i].clear();
    }
    memset(vis,0,sizeof(vis));
    memset(f,0,sizeof(f));
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&w[i]);
    }
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    ans=0;
    dfs(1);

    cout<<ans<<endl;
    return 0;
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值