• 牧场行走(LCA)


    神奇传送门

    好吧,这题很有意思。。

    第一眼撇的时候还以为是(SPFA)呜。。。。

    然后发现要Q次询问就想到了LCA

    但是发现不是求LCA。。

    于是想到了一个神奇的定律:

    两点的LCA一定在u到v的最短路上。。

    并且也一定在两点与根节点的路上。

    所以用dis[a]+dis[b]-2*dis[LCA(a,b)]就得到答案啦!

    这道题有一个坑点!注意!

    我们先来看一个测试:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    int main(){
        int x,y;
        scanf("%d%d",&x,&y);
        int k1=(int)(log(y-x+1.0)/log(2.0));
        int k2=0;
        while(1<<(k2+1)<=y-x+1)k2++;
        printf("%d     %d",k1,k2);
    }

    这看起来是等价的。。但是。。

    输入:1 8

    输出:2      3

    恩,你没有看错,就是2、3.

    事实是这样的:C++ 计算log(8)/log(2)时,得到的答案为(double)2.9999996。

    强制转换为int后,变成了2;

    但是这样就可以了QAQ

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    int main(){
        int num;
        int num2;
        double k=log(8.0)/log(2.0);
        num2=k;
        printf("%d",num2);
    }

    恩,这样就是啦awa

    万恶的C++。。。

    下面贴代码

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    using namespace std;
    struct data{
        int to,next,value;
    }g[5000];
    int head[1001];
    bool qs[1001];
    int id[1001];
    int vs[5000];
    int depth[5000];
    int dp[5000][20];
    int dd[1001];
    int dfs_clock=1;
    int n,q,num=0,root;
    void ins(int a,int b,int v){
        g[++num].next=head[a];
        head[a]=num;
        g[num].to=b;
        g[num].value=v;
    }
    void dfs(int u,int fa,int d){
        id[u]=dfs_clock;
        vs[dfs_clock]=u;
        depth[dfs_clock++]=d;
        for(int i=head[u];i;i=g[i].next)
        {
            int v=g[i].to;
            if(v==fa) continue;
            dd[v]=dd[u]+g[i].value;
            dfs(v,u,d+1);
            vs[dfs_clock]=u;
            depth[dfs_clock++]=d;    
        }
    }
    void RMQ(int nn){
        for(int i=1;i<=nn;i++)
        dp[i][0]=i;
        for(int j=1;(1<<j)<=nn;j++)
        for(int i=1;i+(1<<j)-1<=nn;i++)
        {
            int a=dp[i][j-1];
            int b=dp[i+(1<<(j-1))][j-1];
            if(depth[a]<=depth[b])
            dp[i][j]=a;
            else 
            dp[i][j]=b;
        }
    }
    int cal(int x,int y){
        double k2=log(y-x+1.0)/log(2.0);
        int k=k2;
        int a=dp[x][k];
        int b=dp[y-(1<<k)+1][k];
        if(depth[a]<=depth[b])
        return a;
        else return b;    
    }
    int lca(int u,int v){
        int x=id[u];
        int y=id[v];
        if(x<y)
        return vs[cal(x,y)];
        else return vs[cal(y,x)];
    }
    int main(){
        scanf("%d%d",&n,&q);
        for(int i=1;i<n;i++)
        {
            int a,b,v;
            scanf("%d%d%d",&a,&b,&v);
            qs[b]=1;
            ins(a,b,v);ins(b,a,v);    
        }
        dfs(1,0,0);
        RMQ(dfs_clock-1);
        for(int i=1;i<=q;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            printf("%d
    ",dd[a]+dd[b]-2*dd[lca(a,b)]);
        }
    } 

    不会RMQ的可以看我的传送门

    当然,要打树上倍增的也是可以啦。。

    代码就不贴了。

    真是奇特的题目233~

  • 相关阅读:
    JS截取字符串方法实例
    Adobe Flash Builder 4.6 打开时提示Failed to create the Java Virtual Machine
    ionic 上拉菜单(ActionSheet)安装和iOS样式不一样
    Echarts柱状图百分比显示
    js替换数组中字符串实例
    jQuery获取json数据
    ionic左滑删除
    JavaScript修改日期格式
    ionic之angular1.X缓存问题解决
    angularjs1.X获取前一天日期
  • 原文地址:https://www.cnblogs.com/ghostfly233/p/6836916.html
Copyright © 2020-2023  润新知