码迷,mamicode.com
首页 > 其他好文 > 详细

From Tree to Graph lca 并查集

时间:2019-10-02 20:48:56      阅读:97      评论:0      收藏:0      [点我收藏+]

标签:比赛   操作   alt   重复   display   sed   src   include   str   

  题意: 给定一棵树 当前树的答案为 $f[1]^f[2]^f[3]^..^f[n]$     f[i]表示去除掉i点 该树的联通块数量   

  有m次操作  每次将两个点连一条边   然后再输出该树的答案

 

题目

题解: 显然一开始的时候  答案为每个点的答案为其度  所以可以处理好一开始的答案

    如果将两个点连在一起的时候  那么该路径所经过的点(不包括这两个端点) 的答案都会减一   

           但是考虑到有时候会重复更新   可以将每个点转移到他到儿子的边上  显然 他有多少个儿子就可以被减多少次答案   正好匹配上了

    用并查集来维护点的归属  所以每条边只会被遍历一次  那么复杂度就是  均摊了复杂度m

    比赛的时候被lca卡了   写的是树剖lca   其实可以暴力预处理出所有的lca

技术图片
#include<bits/stdc++.h>
using namespace std;
const int N=5e3+10;
int f[N],n,a,b,x[2],y[2],z[2],deg[N],ans,m;
int find1(int x){return f[x]==x?x:f[x]=find1(f[x]);}
int dep[N],fa[N],siz[N],pre[N],id[N],lca[N][N],pos,ncnt,head[N];
struct Edge{int to,nex;}edge[N<<1];
void add(int a,int b){edge[++pos]=(Edge){b,head[a]};head[a]=pos;}
void dfs(int x,int f)
{
    fa[x]=f;dep[x]=dep[f]+1;id[x]=++ncnt;pre[ncnt]=x;siz[x]=1;lca[x][x]=x;
    for(int i=head[x];i;i=edge[i].nex)
    {
        int v=edge[i].to;
        if(v==f)continue;
        dfs(v,x);siz[x]+=siz[v];
        for(int j=id[x];j<id[v];j++)
            for(int k=id[v];k<id[v]+siz[v];k++)
            lca[pre[j]][pre[k]]=lca[pre[k]][pre[j]]=x;
    }
}
void solve(int x,int y)
{
    x=find1(x);
    while(dep[x]>dep[y]+1)
    {
         ans^=deg[fa[x]];
         deg[fa[x]]--;
         ans^=deg[fa[x]];
         f[x]=fa[x];
         x=find1(fa[x]);
    }
}
void init()
{
    for(int i=0;i<=n;i++)f[i]=i,head[i]=0,deg[i]=0;
    ncnt=ans=pos=0;
}
int main()
{
    while(scanf("%d%d%d%d%d%d",&n,&m,&a,&b,&x[0],&y[0])!=EOF)
    {
        int u,v;
        init();
        for(int i=1;i<n;i++)scanf("%d%d",&u,&v),add(u,v),add(v,u),deg[u]++,deg[v]++;
        dfs(0,0);
        for(int i=0;i<n;i++)ans^=deg[i];
        z[0]=ans;
        for(int i=1;i<=m;i++)
        {
            x[1]=(a*x[0]+b*y[0]+z[0])%n;
            y[1]=(b*x[0]+a*y[0]+z[0])%n;
            solve(x[1],lca[x[1]][y[1]]);
            z[0]=ans;x[0]=x[1];y[0]=y[1];
        }
        printf("%d %d\n",x[1],y[1]);
    }
    return 0;
}
View Code

 

From Tree to Graph lca 并查集

标签:比赛   操作   alt   重复   display   sed   src   include   str   

原文地址:https://www.cnblogs.com/bxd123/p/11618282.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!