• SZOJ 167 Lca裸题


    一道.......一道我改了一周的裸题

    无根树建双向边

    无根树建双向边

    无根树建双向边

    重要的事情说三遍(微笑)

    还有要开longlong

    还有双向边不是双倍边(微笑)

    我真是,能把自己气吐血10次就不把自己气吐血9次

    【问题描述】

    已知一棵nn个点的树,点从1开始标号,树上每条边都有一个正整数边权。

    qq个询问,每个询问由type,u,vtype,u,v三个正整数构成。

    type=1type=1时,询问uu到vv路径上所有边权的二进制异或和。

    type=2type=2时,询问uu到vv路径上所有边权之和。

    type=3type=3时,询问uu到vv路径上边权的最大值。

    【输入格式】

    第一行两个正整数n,qn,q,表示节点个数与询问数。

    接下来nn-11行,每行三个正整数u,v,wu,v,w,表示编号为uu的节点与编号为vv的节点之间有一条权值为ww的边,保证给定的是一棵树。

    接下来qq行,每行三个正整数type,u,vtype,u,v,表示一个询问。

    【输出格式】

    对每个询问输出一行表示答案。

    【样例输入】
    4 4
    1 2 1
    2 3 3
    2 4 4
    1 1 3
    1 3 4
    2 1 4
    3 1 3
    【样例输出】
    2
    7
    5
    3
    【数据规模】

    对于40%40%的数据,type=1type=1

    对于80%80%的数据,type2type≤2

    对于100%100%的数据,2n,q300000,1w109,1type32≤n,q≤300000,1≤w≤109,1≤type≤3。

    对于至少25%25%的数据,树是随机生成的,这些数据会在所有测试点中比较均匀地分布。 

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    using namespace std;
    stack<int> s;
    int g[600001],dep[600001],n,cnt,T,q,sum2[600001];
    long long sum1[600001];
    int f[600001][21],g1[600001][21];
    int root1;
    struct node{
        int nxt,to,w,fr;
    }e[600001];
    inline void addedge(int x,int y,int z){
        e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;e[cnt].w=z;e[cnt].fr=x;
    }
    inline void dfs(int u){
        dep[u]=1;s.push(u);
        while(!s.empty()){
            u=s.top();s.pop();
           for(int i=1;i<=19;i++)
                   f[u][i]=f[f[u][i-1]][i-1];
            for(int i=1;i<=19;i++)
                g1[u][i]=max(g1[u][i],max(g1[f[u][i-1]][i-1],g1[u][i-1]));
            for(int i=g[u];i;i=e[i].nxt){
                if(!dep[e[i].to]){
                    dep[e[i].to]=dep[u]+1;
                    f[e[i].to][0]=u;
                    g1[e[i].to][0]=e[i].w;
                    s.push(e[i].to);
                }
            }
        }
    }
    inline int swim(int x,int h){
        for(int i=0;h;i++,h>>=1)
            if(h&1) x=f[x][i];
        return x;
    }
    inline int swim1(int x,int h){
        int maxnum=-100007;
        for(int i=0;h;i++,h>>=1)
            if(h&1){
                maxnum=max(maxnum,g1[x][i]);
                x=f[x][i];
    //            printf("g1=%d maxnum=%d
    ",g1[x][i],maxnum);
            }
    //    printf("mmmax==%d
    ",maxnum);
        return maxnum;
    }
    inline int Lca(int x,int y){
        if(dep[x]<dep[y]){
            int t;
            t=x;
            x=y;
            y=t;
        }
        x=swim(x,dep[x]-dep[y]);
        if(x==y) return x;
        for(int i=19;~i;i--){if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];}
        return f[x][0];
    }
    inline int Lca1(int x,int y){
        if(dep[x]<dep[y]){
            int t;
            t=x;
            x=y;
            y=t;
        }
        int maxnum=swim1(x,dep[x]-dep[y]);
    //    printf("swim1 maxnum=%d %d %d
    ",maxnum,x,dep[x]-dep[y]);
        x=swim(x,dep[x]-dep[y]);
        if(x==y) return maxnum;
        for(int i=19;~i;i--){
            if(f[x][i]!=f[y][i]){
                maxnum=max(maxnum,max(g1[x][i],g1[y][i]));
                x=f[x][i],y=f[y][i];
            }
        }
        maxnum=max(maxnum,max(g1[x][0],g1[y][0]));
        return maxnum;
    }
    inline void dfs1(int u){
        s.push(u);
        while(!s.empty()){
            u=s.top();s.pop();
            for(int i=g[u];i;i=e[i].nxt){
                if(e[i].to==f[u][0])continue;
                s.push(e[i].to);
                sum1[e[i].to]=sum1[u]+e[i].w;
                sum2[e[i].to]=sum2[u]^e[i].w;
            }
        }
    }
    inline void Jimmy(){
        scanf("%d%d",&n,&q);
        for(int i=1,u,v,w;i<=n-1;i++){
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);addedge(v,u,w);
        }
    
        //f[1][0]=1;
        dfs(1);
        //for(int i=1;i<=n;i++)cout<<f[i][0]<<",";
        dfs1(1);
        //cout<<sum2[5]<<","<<sum2[1]<<endl;
       for(int i=1,u1,v1,ty;i<=q;i++){
            scanf("%d%d%d",&ty,&u1,&v1);
            if(ty==1) printf("%d
    ",sum2[u1]^sum2[v1]);
            if(ty==2) printf("%lld
    ",sum1[u1]+sum1[v1]-2*sum1[Lca(u1,v1)]);
            if(ty==3) printf("%d
    ",Lca1(u1,v1));
        }
    //    printf("FFFFFFFFF    %d %d
    ",g1[3][0],g1[3][1]);
        return;
    }
    int main(){
            Jimmy();
        return 0;
    }
    View Code

    (微笑)

  • 相关阅读:
    设计模式(连载)
    菜鸟成长记录——2015-2016半年总
    订餐系统——TreeView显示目录结构
    网上商城——ApplicationContext.xml
    订餐系统——Gridview、Repeater和DataList 区别
    订餐系统——后台获取GridView值
    网上商城——邮件发送(二)
    网上商城——邮件发送(一)
    J2EE基础概念
    工作流——顺序工作流
  • 原文地址:https://www.cnblogs.com/JimmyC/p/6426248.html
Copyright © 2020-2023  润新知