P3128 [USACO15DEC] Max Flow P

原题链接

题解

1.修改树上某一段路径 ,最后问你单个点的最大值,很想区间修改,单点查询,且只查询一遍,所以我们往前缀和方向靠
2.一个节点只有一个父亲,所以从底到根的路径是一条链,我们可以在这里应用前缀和,标记策略为令 tree[now]++ 代表 now 节点到根节点这条链上所有节点都加一, 令 tree[now] 代表 now 节点到根节点这条链上所有节点都减一,转移策略为一继承所有子节点的状态
3.由于无法确定两个点之间的父亲/兄弟关系,所以标记策略为 tree[x]++,tree[y]++,tree[lca],tree[fa[lca][0]]

code

#include<bits/stdc++.h>
using namespace std;
vector<int> G[50005];
int depth[50005]={0};
int fa[50005][30]={0};
int n,k;
int tree[50005]={0};
void dfs(int now,int pre)
{
    fa[now][0]=pre;
    for(auto next:G[now])
    {
        if(next==pre) continue;
        depth[next]=depth[now]+1;
        dfs(next,now);
    }
}

int lca(int x,int y)
{
    if(depth[x]<depth[y]) swap(x,y);

    for(int i=20;i>=0;i--) if(depth[fa[x][i]]>=depth[y]) x=fa[x][i];

    if(x==y) return x;
    for(int i=20;i>=0;i--)
    {
        if(fa[x][i]!=fa[y][i])
        {
            x=fa[x][i];
            y=fa[y][i];
        }
    }

    return fa[x][0];
}

int ans=0;
void cal(int now,int pre)
{
    for(auto next:G[now])
    {
        if(pre==next) continue;
        cal(next,now);
        tree[now]+=tree[next];
    }
    ans=max(ans,tree[now]);
}

int main()
{
    cin>>n>>k;
    for(int i=1;i<n;i++)
    {
        int x,y;
        cin>>x>>y;
        G[x].push_back(y);
        G[y].push_back(x);
    }

    depth[1]=1;
    dfs(1,0);

    for(int k=1;k<=20;k++)
    {
        for(int i=1;i<=n;i++)
        {
            fa[i][k]=fa[fa[i][k-1]][k-1];
        }
    }

    for(int i=1;i<=k;i++)
    {
        int x,y;
        cin>>x>>y;
        tree[x]++;
        tree[y]++;
        int f=lca(x,y);
        tree[f]--;
        tree[fa[f][0]]--;
    }


    cal(1,0);

    cout<<ans<<endl;

    return 0;
}

posted @   纯粹的  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示