【学术篇】树上差分--洛谷3128最大流Max Flow

懒得贴题目,直接放不稳定的传送门(雾):点击前往暴风城(雾)

据说这题是BZOJ3490,但本蒟蒻没有权限╮(╯_╰)╭

这题似乎就是裸树上差分。。。

对于树上(x,y)之间的路径上的点区间c[i]加k<==>c[x]+=k,c[y]+=k,c[lca(x,y)]-=k,c[father[lca(x,y)]-=k

就是这样,虽然这题我因为各种智障的原因luogu上交了3遍,为拉低这题通过率做出了巨大的贡献。。。

最后统计的时候从树根dfs一遍,把子节点的c值加到父节点上就行了~~

所以这题重点就是求lca(x,y)了,在这里我用了Tarjan,因为比倍增快,而且链剖LCA我也不会(或许也没有Tarjan快)。。

贴代码:

#include<cstdio>
#define N 50005
#define M 100005
#define gc getchar
struct edge
{
    int to,next;
}e[N<<1];
struct ques
{
    int to,next,id;
}f[M<<1];
int n,m,u[N],v[N],c[N],fa[N],up[N],ans[M],tot,tit=0,maxn=0;
bool vis[N],vis2[N];
int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
void qin(int &a)
{
    a=0;char c=gc();bool f=0;
    for(;(c<'0'||c>'9')&&c!='-';c=gc());
    if(c=='-') f=1,c=gc();
    for(;c>='0'&&c<='9';c=gc()) a=a*10+c-'0';
    if(f) a=-a;
}
void build(int x,int y)
{
    e[++tot].to=y; e[tot].next=v[x]; v[x]=tot;
    e[++tot].to=x; e[tot].next=v[y]; v[y]=tot;
}
void quest(int x,int y,int z)
{
    f[++tit].to=y; f[tit].next=u[x]; u[x]=tit; f[tit].id=z;
    f[++tit].to=x; f[tit].next=u[y]; u[y]=tit; f[tit].id=z;
}
void dfs(int x)
{
    vis[x]=1; fa[x]=x;
    for(int i=v[x];i;i=e[i].next)
        if(!vis[e[i].to])
            up[e[i].to]=x,dfs(e[i].to),fa[e[i].to]=x;
    for(int i=u[x];i;i=f[i].next)
        if(vis[f[i].to])
            ans[f[i].id]=find(f[i].to);
}
void dfs2(int x)
{
    vis2[x]=1;
    for(int i=v[x];i;i=e[i].next)
    {
        int y=e[i].to;
        if(!vis2[y]) dfs2(y),c[x]+=c[y];
    }
    if(c[x]>maxn) maxn=c[x];
}
int main()
{
    qin(n);qin(m);
    for(int i=1;i<n;i++)
    {
        int a,b;qin(a),qin(b);
        build(a,b);
    }
    for(int i=1;i<=m;i++)
    {
        int a,b;qin(a),qin(b);
        c[a]++;c[b]++;
        quest(a,b,i);
    }
    dfs(1);
    for(int i=1;i<=m;i++)
        c[ans[i]]--,c[up[ans[i]]]--;    
    dfs2(1);
    printf("%d
",maxn);
}

嗯 就是这样。。。

原文地址:https://www.cnblogs.com/enzymii/p/8412163.html