zoukankan      html  css  js  c++  java
  • 倍增法求lca:暗的连锁

    https://loj.ac/problem/10131

    #include<bits/stdc++.h>
    using namespace std;
    struct node{
        int to,next;
    }e[1000001];
    int head[500000],num=0,N,n,m,ans;
    int grand[500001][20],depth[500001];
    int f[100000],w[1000000];
    inline void add(int x,int y)
    {
        e[++num].to=y,e[num].next=head[x],head[x]=num;
    }
    inline void read(int &x)
    {
        x=0;int f=1;
        char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        x*=f;
    }
    void dfs(int x)
    {
        for(int i=1;i<=N;i++)grand[x][i]=grand[grand[x][i-1]][i-1];
        for(int i=head[x];i;i=e[i].next)
        {
            int v=e[i].to;
            if(v==grand[x][0])continue;
            depth[v]=depth[x]+1;
            grand[v][0]=x;
            dfs(v);
        }
    }
    void init()
    {
        N=floor(log(n+0.0)/log(2.0));
        depth[1]=1;
        dfs(1);
    }
    inline int lca(int a,int b)
    {
        if(depth[a]>depth[b]) swap(a,b);
        for(register int i=N;i>=0;i--)
        {
            if(depth[a]<depth[b]&&depth[grand[b][i]]>=depth[a]) b=grand[b][i];
        }
        if(a==b)return a;
        for(register int i=N;i>=0;i--)
        {
            if(grand[a][i]!=grand[b][i]){a=grand[a][i],b=grand[b][i];}
        }
        return grand[a][0];
    }
    void solve(int u,int fa)
    {
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;if(v==fa) continue;
            solve(v,u);f[u]+=f[v];
        } 
    }
    int main()
    {
        read(n),read(m);
        for(int i=1;i<n;i++)
        {
            int u,v;
            read(u),read(v);
            add(u,v);
            add(v,u);
        }
        init();
        for(int i=1;i<=m;i++)
        {
            int x,y;
            read(x),read(y);
            w[x]++;w[y]++;
            w[lca(x,y)]-=2;
        }
        for(int i=1;i<=n;i++) f[i]=w[i];
        solve(1,0);
        for(int i=2;i<=n;i++)
        {
            if(f[i]==0) ans+=m;
            else if(f[i]==1) ans++;
        }
        cout<<ans;
    }
  • 相关阅读:
    Linux下一个patch补丁命令
    资本中国人物-金融
    深入浅出JMS(一)——JMS简要
    在JBuilder8在使用ANT
    mysql存储引擎
    Linux系统监控
    SIEM
    mysql主从数据库复制
    JVM中可生成的最大Thread数量
    磁盘IO性能监控(Linux 和 Windows)
  • 原文地址:https://www.cnblogs.com/719666a/p/9573244.html
Copyright © 2011-2022 走看看