• 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

      

  • 相关阅读:
    关于hibernate中多对多关系
    选择排序
    Offer是否具有法律效力?
    textarea文本域宽度和高度(width、height)自己主动适应变化处理
    序列相关的趣题 之三
    windows的定时任务设置
    Maven pom.xml 配置详解
    PS 图像特效-非线性滤波器
    PS 滤镜算法原理——拼贴
    PS 滤镜算法原理——曝光过度
  • 原文地址:https://www.cnblogs.com/FEIIEF/p/12242079.html
Copyright © 2020-2023  润新知