CF191C Fools and Roads

题目链接:https://www.luogu.com.cn/problem/CF191C

     https://codeforces.com/problemset/problem/191/C

题意:

  给你一棵树,然后给你m对点,将每对点之间的最短路径上每条边权值+1,求操作完成后每条边的权值。

方法:

  p[s]++,p[t]++,p[lca(s,t)]-=2

  用倍增算法计算LCA

代码:

#include <bits/stdc++.h>
#define LL long long
using namespace std;

const int maxn=100000+10;
int lg[maxn];
int n;
struct Edge{
    int to, next;
}e[maxn<<1];
int head[maxn];
int en;
int fa[maxn][22];
int depth[maxn];
int u[maxn];
int v[maxn];

int cf[maxn];

void addEdge(int from, int to){
    e[en].next=head[from];
    e[en].to=to;
    head[from]=en;
    ++en;
}

void dfs(int cur, int pre){
    depth[cur]=depth[pre]+1;
    fa[cur][0]=pre;
    for(int i=1;i<=lg[depth[cur]-1];++i){
        fa[cur][i]=fa[fa[cur][i-1]][i-1];
    }

    for(int i=head[cur];i!=-1;i=e[i].next){
        int v=e[i].to;
        if(v!=pre){
            dfs(v,cur);
        }
    }
}

int lca(int a, int b){
    if(depth[a]<depth[b]) swap(a,b);

    while(depth[a]>depth[b]){
        a=fa[a][lg[depth[a]-depth[b]]];
    }

    if(a==b) return a;

    for(int i=lg[depth[a]];i>=0;--i){
        if(fa[a][i]!=fa[b][i]){
            a=fa[a][i];
            b=fa[b][i];
        }
    }

    return fa[a][0];
}

void dfs2(int cur, int pre){
    for(int i=head[cur];i!=-1;i=e[i].next){
        int ve=e[i].to;
        if(ve!=pre){
            dfs2(ve,cur);
            cf[cur]+=cf[ve];
        }
    }
}

int main(){
    memset(head,-1,sizeof(head));
    scanf("%d", &n);
    lg[1]=0;
    lg[2]=1;
    for(int i=3;i<=n;++i){
        if(i==(1<<(lg[i-1]+1))){
            lg[i]=lg[i-1]+1;
        }else{
            lg[i]=lg[i-1];
        }
    }
    for(int i=1;i<=n-1;++i){

        scanf("%d %d", &u[i], &v[i]);
        addEdge(u[i],v[i]);
        addEdge(v[i],u[i]);
    }
    dfs(1,0);
    int k;
    scanf("%d", &k);
    for(int i=1;i<=k;++i){
        int a,b;
        scanf("%d %d", &a, &b);
        int c=lca(a,b);
        ++cf[a];
        ++cf[b];
        cf[c]-=2;

    }

    dfs2(1,0);

    for(int i=1;i<=n-1;++i){
        if(depth[u[i]]>depth[v[i]]){
            printf("%d ", cf[u[i]]);
        }else {
            printf("%d ", cf[v[i]]);
        }
    }
    return 0;
}  

 参考:

https://www.luogu.com.cn/blog/eps/cf191fools-and-roads

  

原文地址:https://www.cnblogs.com/FEIIEF/p/12242079.html