倍增法求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;
}

 

posted @ 2018-09-02 11:34  南柯一场  阅读(281)  评论(0编辑  收藏  举报