Max Flow

Max Flow

https://ac.nowcoder.com/acm/problem/24019

题意:
有一颗n个节点的树,有k次操作,每次操作给出二个节点,然后将二个节点及二个节点之间的节点权值都加一,然后求最后树中权值最大的节点的权值为多少?

思路:
lca+差分:
用lca求出二个节点u、v的最近公共祖先k,k的父亲节点为kp;
要使u、v路经上节点权值加一则val[u]、val[v]进行加一,表示经过u、v节点时值加一,然后k位置此时相当与加了二,所以val[k]要减一,最后val[kp]减一表示经过kp节点时值减一。
求点的权值时从叶子节点开始向根节点计算,取最大值当结果即可。

代码:

#include<bits/stdc++.h>

#define ll long long
#define eps 1e-8

using namespace std;

const ll inf=1e9+7;

int val[100005], dep[100005], parent[21][100005], qi=0, ma=0;

vector<int> g[100005];

void dfs(int v,int f,int k)
{
    dep[v]=k;
    parent[0][v]=f;
    for(int i=0; i<g[v].size(); i++)
    {
        int u=g[v][i];
        if(u==f)
        {
            continue;
        }
        dfs(u,v,k+1);
    }
}

int dfs1(int v,int f)
{
    int z=val[v];
    for(int i=0; i<g[v].size(); i++)
    {
        int u=g[v][i];
        if(u==f)
        {
            continue;
        }
        z=z+dfs1(u,v);
    }
    ma=max(ma,z);
    return z;
}

int quitv(int u,int v)
{
    if(dep[u]<dep[v])
    {
        swap(u,v);
    }
    int k=dep[u]-dep[v];
    for(int i=18; i>=0; i--)
    {
        if((k>>i)&1)
        {
            u=parent[i][u];
        }
    }
    if(u==v)
    {
        return u;
    }
    for(int i=18; i>=0; i--)
    {
        if(parent[i][u]!=parent[i][v])
        {
            u=parent[i][u];
            v=parent[i][v];
        }
    }
    return parent[0][u];
}

int main()
{
    int n, q;
    scanf("%d%d",&n,&q);
    for(int i=1; i<n; i++)
    {
        int u, v;
        scanf("%d%d",&u,&v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(1,-1, 1);
    for(int k=1; k<=18; k++)
    {
        for(int i=1; i<=n; i++)
        {
            if(parent[k-1][i]==-1)
            {
                parent[k][i]=-1;
            }
            else
            {
                parent[k][i]=parent[k-1][parent[k-1][i]];
            }
        }
    }
    while(q--)
    {
        int u, v;
        scanf("%d%d",&u,&v);
        int k=quitv(u,v);
        val[k]--;
        if(parent[0][k]!=-1)
            val[parent[0][k]]--;
        val[u]++;
        val[v]++;
    }
    dfs1(1,-1);
    cout << ma << endl;
    return 0;
}
每日一题题解 文章被收录于专栏

写题解

全部评论

相关推荐

2025-12-19 15:17
门头沟学院 Java
27届中九本,目前陆陆续续也面了很多家厂了,大厂面了字节、腾讯、虾皮还有几家中小厂,全是一面挂,只有字节进二面,二面也是秒挂了。知道自己能力很差,基本上大厂面试题只要问题不是八股文,出一些场景题或者真实情况下的一些问题就不太答得上来,我感觉大多数面试官看我项目都是学习性质的项目没有部署上线,也没有面对真实场景好像就对我的项目没啥兴趣了,项目也不太拷打,就问几个简单的八股或者直接另出一个系统设计题(比如字节、虾皮),有一家中厂问的八股啥的还让我介绍项目重点,我就介绍然后正常回答八股,他也不追问,但是莫名就是一面挂了,也想问问大家有什么星球上的项目推荐嘛。目前项目就是一个点评魔改加一个图库烂大街,昨天面的腾讯的面试官人很好,也给我指出了一些建议,希望我深耕一些技术的实际场景不要堆砌中间件还要加深计算机基础知识的学习。因为楼主不是科班的,数据结构因为学过,Hot100也刷烂了,算法只要不是很难问题应该不大,但是计算机网络操作系统完全没学过,面腾讯和虾皮的时候完全不会被拷打了,感觉这些知识也不好速成,加上最近要期末考试了,学习技术的时间也要压缩分担给课上突击一下期末。想先沉淀半个多月,度过期末再做个项目之后继续投,想问一下各位大佬有什么意见?真的有点迷茫,感觉还要学好多才能达到找实习的水平,如果一月还找不到就打算考研了,那些真实场景确实没有接触过考虑不到,但是我都没有工作经验感觉很难锻炼这方面,也想问问大家该怎么提高这种真实场景思维,谢谢各位佬。
纳斯卡可:哥们大厂不要乱面啊,这些都是有面评的。你下次再想去面试都不会给你约了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务