POJ 3417(Acwing 352)——闇の連鎖

 

树上差分+树剖LCA

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;
const int  N = 1e5+10,M=2*2e5+10;

struct Edge{
    int to,next,w;
}edge[M];int idx;
int h[N];
int n,m;
int f[N];
int size[N],fa[N],son[N];
int top[N],dep[N];


void add(int u,int v)
{
    edge[++idx].to=v;
    edge[idx].next=h[u];
    h[u]=idx;
}

void dfs1(int s,int f)
{
    fa[s]=f;
    size[s]=1;
    dep[s]=dep[f]+1;
    int wson=-1;
    for(int i=h[s];~i;i=edge[i].next)
    {
        int to=edge[i].to;
        if(to==f)continue;
        dfs1(to,s);
        size[s]+=size[to];
        if(size[to]>wson)wson=size[to],son[s]=to;
    }
}

void dfs2(int s,int t)
{
    top[s]=t;
    if(!son[s])return;
    dfs2(son[s],t);
    for(int i=h[s];~i;i=edge[i].next)
    {
        int to=edge[i].to;
        if(to==fa[s] || to==son[s])continue;
        dfs2(to,to);
    }
}

inline int lca(int a,int b)
{
    while(top[a]!=top[b])
    {
        if(dep[top[a]]<dep[top[b]])swap(a,b);
        a=fa[top[a]];
    }
    return dep[a]<dep[b] ? a : b;
}

void dfs(int k)
{
    for(int i=h[k];~i;i=edge[i].next)
    {
        int to=edge[i].to;
        if(to==fa[k])continue;
        dfs(to);
        f[k]+=f[to];
    }
}

void init()
{
    memset(h,-1,sizeof h);
}

int main()
{
    scanf("%d%d",&n,&m);
    init();
    for(int i=1;i<=n-1;i++)
    {
        int a,b;scanf("%d%d",&a,&b);
        add(a,b);
        add(b,a);
    }
    dfs1(1,0);
    dfs2(1,1);
    
    for(int i=1;i<=m;i++)
    {
        int a,b;scanf("%d%d",&a,&b);
        f[a]++;f[b]++;
        f[lca(a,b)]-=2;
    }
    
    dfs(1);
    
    int ans=0;
    for(int i=2;i<=n;i++)
    {
        if(f[i]==0)ans+=m;
        else if(f[i]==1)ans++;
        else continue;
    }
    
    printf("%d\n",ans);
    
    return 0;
}

 

posted @ 2019-10-05 11:15  魑吻丶殇之玖梦  阅读(99)  评论(0)    收藏  举报