D. The Fair Nut and the Best Path 树形dp (终于会了)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=3e5+10;
int a[maxn];
int dp[maxn];
int visit[maxn];
vector<int> vs[maxn];
map<pair<int,int>,int> mp;
int ans=0;
void dfs(int x)
{
    visit[x]=1;
    int max1=0;
    int max2=0;
    for(int i=0;i<vs[x].size();i++)
    {

        int p=vs[x][i];
        if(visit[p]) continue;//cout<<p<<endl;
        dfs(p);
        int k=dp[p]-mp[{x,p}];
        if(k>=max1) max2=max1,max1=k;
        else if(k>=max2) max2=k;
    }
    //cout<<x<<"  "<<dp[x]<<endl;
    dp[x]=a[x]+max1;
    ans=max(ans,dp[x]);
    ans=max(ans,max1+max2+a[x]);
}
int32_t main()
{
    int n; cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) dp[i]=a[i];
    for(int i=1;i<n;i++)
    {
        int x,y,z; cin>>x>>y>>z;
        vs[x].push_back(y); mp[{x,y}]=z;
        vs[y].push_back(x); mp[{y,x}]=z;
    }
    dfs(1);
    cout<<ans<<endl;
    return 0;
}

2994ms

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=3e5+10;
int a[maxn];
int dp[maxn];
int visit[maxn];
vector<pair<int,int> > vs[maxn];
int ans=0;
void dfs(int x)
{
    visit[x]=1;
    int max1=0;
    int max2=0;
    for(int i=0;i<vs[x].size();i++)
    {

        int p=vs[x][i].first;
        if(visit[p]) continue;//cout<<p<<endl;
        dfs(p);
        int k=dp[p]-vs[x][i].second;
        if(k>=max1) max2=max1,max1=k;
        else if(k>=max2) max2=k;
    }
    //cout<<x<<"  "<<dp[x]<<endl;
    dp[x]=a[x]+max1;
    ans=max(ans,dp[x]);
    ans=max(ans,max1+max2+a[x]);
}
int32_t main()
{
    int n; cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) dp[i]=a[i];
    for(int i=1;i<n;i++)
    {
        int x,y,z; cin>>x>>y>>z;
        vs[x].push_back({y,z}); //mp[{x,y}]=z;
        vs[y].push_back({x,z}); //mp[{y,x}]=z;
    }
    dfs(1);
    cout<<ans<<endl;
    return 0;
}

2308ms

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=3e5+10;
int a[maxn];
int dp[maxn];
int visit[maxn];
vector<pair<int,int> > vs[maxn];
int ans=0;
void dfs(int x)
{
    visit[x]=1;
    int max1=0;
    int max2=0;
    for(int i=0;i<vs[x].size();i++)
    {

        int p=vs[x][i].first;
        if(visit[p]) continue;//cout<<p<<endl;
        dfs(p);
        int k=dp[p]-vs[x][i].second;
        if(k>=max1) max2=max1,max1=k;
        else if(k>=max2) max2=k;
    }
    //cout<<x<<"  "<<dp[x]<<endl;
    dp[x]=a[x]+max1;
    ans=max(ans,dp[x]);
    ans=max(ans,max1+max2+a[x]);
}
int32_t main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n; cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) dp[i]=a[i];
    for(int i=1;i<n;i++)
    {
        int x,y,z; cin>>x>>y>>z;
        vs[x].push_back({y,z}); //mp[{x,y}]=z;
        vs[y].push_back({x,z}); //mp[{y,x}]=z;
    }
    dfs(1);
    cout<<ans<<endl;
    return 0;
}

700+ms

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=3e5+10;
int a[maxn];
int dp[maxn];
int visit[maxn];
vector<pair<int,int> > vs[maxn];
int ans=0;
void dfs(int x)
{
    visit[x]=1;
    int max1=0;
    int max2=0;
    for(int i=0;i<vs[x].size();i++)
    {

        int p=vs[x][i].first;
        if(visit[p]) continue;//cout<<p<<endl;
        dfs(p);
        int k=dp[p]-vs[x][i].second;
        if(k>=max1) max2=max1,max1=k;
        else if(k>=max2) max2=k;
    }
    //cout<<x<<"  "<<dp[x]<<endl;
    dp[x]=a[x]+max1;
    ans=max(ans,dp[x]);
    ans=max(ans,max1+max2+a[x]);
}
int32_t main()
{
    /*ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);*/
    int n; scanf("%I64d",&n);
    for(int i=1;i<=n;i++) scanf("%I64d",&a[i]);
    for(int i=1;i<=n;i++) dp[i]=a[i];
    for(int i=1;i<n;i++)
    {
        int x,y,z; scanf("%I64d %I64d %I64d",&x,&y,&z);
        vs[x].push_back({y,z}); //mp[{x,y}]=z;
        vs[y].push_back({x,z}); //mp[{y,x}]=z;
    }
    dfs(1);
    printf("%I64d\n",ans);
    return 0;
}

405ms

原文地址:https://www.cnblogs.com/Andromeda-Galaxy/p/10115989.html

时间: 2024-08-06 14:21:11

D. The Fair Nut and the Best Path 树形dp (终于会了)的相关文章

CodeForces 1084D The Fair Nut and the Best Path

The Fair Nut and the Best Path 题意:求路径上的 点权和 - 边权和 最大, 然后不能存在某个点为负数. 题解: dfs一遍, 求所有儿子走到这个点的最大值和次大值. 我们需要明白如果可以从u -> v  那么一定可以从 v -> u, 当然 指的是 u->v是路径上的最大和. u->e1->v; 假如:val[u] = 100, val[e1] = 50, val[v] = 60, 那么我们发现可以从 u -> v 也可以从v ->

Codeforces Round #526 (Div. 2) D. The Fair Nut and the Best Path

D. The Fair Nut and the Best Path 题目链接:https://codeforces.com/contest/1084/problem/D 题意: 给出一棵树,走不重复的路径,每到一个结点加上其权值,经过一条边减去其权值,路径中途减去后不能出现负数,问怎么选择路径可以让最后得到的最大. 题解: 这题考虑用dp来做. 我们定义dp[u]为走到u点的最大值,注意这里的方向,是走到u点.题目中的意思是路径不能走回头路. 对于一个父节点u,那么我们可以根据走到其儿子结点的最

D. The Fair Nut and the Best Path

https://codeforces.com/contest/1084/problem/D?tdsourcetag=s_pctim_aiomsg 题意:一个树,点有值,边有值,求任意两点之间的最大值,遇到点要加它对应的值,遇到边减掉它对应的值. 思路:嗯,题意理解做法水的一笔,任意两点的路径的最大值,可以采用dfs,回溯到父亲结点,与它两个较大的(可能一个或零个)子节点的路径构成最大路径. #include<bits/stdc++.h> using namespace std; #define

Codeforces Round #526 (Div. 2) C. The Fair Nut and String

C. The Fair Nut and String 题目链接:https://codeforces.com/contest/1084/problem/C 题意: 给出一个字符串,找出都为a的子序列(比如ai,aj,ak)满足以下条件的个数: 1.子序列的索引单增(i<j<k): 2.在原字符串中,若ai=aj=ak=a,那么满足i<=k1<j,j<=k2<k 并且 ak1=ak2=b. 通俗点说,就是找这样的子序列个数:要么单个a,要么每个a之间都有一个b. 题解:

Codeforces Round #526 (Div. 2) E. The Fair Nut and Strings

E. The Fair Nut and Strings 题目链接:https://codeforces.com/contest/1084/problem/E 题意: 输入n,k,k代表一共有长度为n的多少个字符串.然后给出一个最小字符串s,最大字符串t,满足对于所有的k个字符串有s<=S<=t. 最后求满足条件的k个字符串(自己构造)的不同前缀数量的和. 题解: 这题很巧妙,设dp(i)表示长度为i的前缀的数量和,一开始有dp(1)=0. 后来随着长度的增加,我们每次可以在最后加一个a或者b,

CodeForces 1084A The Fair Nut and Elevator 题解

A. The Fair Nut and Elevator time limit per test : 1 second memory limit per test : 256 megabytes input : standard input output : standard output The Fair Nut lives in ?? story house. ???? people live on the ??-th floor of the house. Every person use

HDU4916 Count on the path(树dp??)

这道题的题意其实有点略晦涩,定义f(a,b)为 minimum of vertices not on the path between vertices a and b. 其实它加一个minimum index of vertices应该会好理解一点吧.看了一下题解,还有程序,才理清思路. 首先比较直接的是如果两点的路径没有经过根节点1的话,那么答案就直接是1,否则的话就必然有从根节点出发的两条路径,题解里说的预处理出f[u]表示不在根节点到u的路径上的点的最小值,然后取f[u]和f[v]的最小

Codeforces Round #526 C - The Fair Nut and String /// 组合递推

题目大意: 给定原字符序列 找出其中所有子序列满足 1.序列内字符都为a 2.若有两个以上的字符 则相邻两个字符在原序列中两者之间存在字符b 的数量 将整个字符序列用b分开 此时再得到每个b之间a的数量 即 abbgaaba 得到 v[] = { 1 0 2 1 } 此时假设到第 i-1 段 已得到在第 i-1 段内的所有方案数为 ans (长度为1.2.3.... .i-1) 则在第 i 段时 可由前一段的方案数 和 当前段数量 组合得到ans*v[ i ] (长度为2.3.4.... .i)

[CF1083B]The Fair Nut and Strings

题目大意:在给定的长度为$n(n\leqslant5\times10^5)$的字符串$A$和字符串$B$中找到最多$k$个字符串,使得这$k$个字符串不同的前缀字符串的数量最多(只包含字符$a$和$b$). 题解:考虑给这$k$个字符串建一个$trie$树,答案就是它所含的节点数,考虑贪心,在每一层尽可能多的分叉.注意一层最多只能有$k$个点 卡点:无 C++ Code: #include <cstdio> #define maxn 500010 int n, k; long long ans