zoukankan      html  css  js  c++  java
  • poj2763 Housewife Wind LCA

    题目链接:

    http://poj.org/problem?id=2763

    题意:

    一个无根树,给出主角一开始所在的位置S,然后下面q个操作,操作包括查询和修改操作,对于查询操作就是当前主角的位置到目的点的距离是多少,然后主角去到那里之后就在那里等待,下次查询的时候那里就是新的起点(所以sample中第二次查询为什么是3)。修改是修改第k条边的权值,边的编号就是输入的顺序。

    思路:

    求树上两点之间的距离,ans=dis[u]+dis[v]-dis[LCA(u,v)]*2;
    求LCA这里是用的倍增的思想, 先让两个点跳到同一深度,然后两个点再同时往上跳,先跳大步。

    还有别的方法求LCA,http://www.cnblogs.com/scau20110726/archive/2013/06/14/3135095.html 这个人的LCA挺好的【离线RMQ】。我觉得还是在线倍增比较好理解
    对于修改,修改一条边,暴力更新dis这个数组,数据水,这样可以通过。
    对于树链剖分的做法 蒟蒻不会

    代码:

    代码一:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    #define MS(a) memset(a,0,sizeof(a))
    #define MP make_pair
    #define PB push_back
    const int INF = 0x3f3f3f3f;
    const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
    inline ll read(){
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    //////////////////////////////////////////////////////////////////////////
    const int maxn = 1e5+10;
    
    struct node{
        int u,v,w,next;
    }e[maxn*2];
    int tot,dp[maxn][25],dep[maxn],head[maxn],dis[maxn];
    
    void add(int u,int v,int w,int &k){
        e[k].u=u; e[k].v=v; e[k].w=w;
        e[k].next=head[u]; head[u]=k++;
        swap(u,v);
        e[k].u=u; e[k].v=v; e[k].w=w;
        e[k].next=head[u]; head[u]=k++;
    }
    
    void dfs(int u,int f){
        dep[u] = dep[f]+1;
        dp[u][0] = f;
        for(int i=head[u]; i!=-1; i=e[i].next){
            int v = e[i].v, w = e[i].w;
            if(v == f) continue;
            dis[v] = dis[u]+w;
            dfs(v,u);
        }
    }
    
    int LCA(int x,int y){
        if(dep[x] < dep[y]) swap(x,y);
        for(int i=20; i>=0; i--)
            if(dep[dp[x][i]]>=dep[y])
                x = dp[x][i];
        if(x == y) return x;
        for(int i=20; i>=0; i--)
            if(dep[dp[x][i]]==dep[dp[y][i]] && dp[x][i]!=dp[y][i])
                x = dp[x][i], y = dp[y][i];
        return dp[x][0];
    }
    
    void change(int u,int f,int val){
        dis[u] += val;
        for(int i=head[u]; i!=-1; i=e[i].next){
            if(f == e[i].v) continue;
            change(e[i].v,u,val);
        }
    }
    
    int main(){
        int n,q,s;
        while(cin>>n>>q>>s){
            tot = 0;
            memset(head,-1,sizeof(head));
            for(int i=1; i<n; i++){
                int u,v,w; scanf("%d%d%d",&u,&v,&w);
                add(u,v,w,tot);
            }
            dfs(1,0);
            for(int i=1; i<=20; i++)
                for(int j=1; j<=n; j++)
                    dp[j][i] = dp[dp[j][i-1]][i-1];
            while(q--){
                int op = read();
                if(op == 0){
                    int v = read();
                    int ans = dis[s]+dis[v]-2*dis[LCA(s,v)];
                    s = v;
                    cout << ans << endl;
                }else{
                    int p,y; scanf("%d%d",&p,&y);
                    p = (p-1)*2;
                    int u = e[p].u, v = e[p].v, w = e[p].w;
                    int t1 = dep[u]<dep[v] ? v:u;
                    int t2 = dep[u]<dep[v] ? u:v;
                    e[p].w = e[p^1].w = y;
                    change(t1,t2,y-w); 
                }
            }
        }
    
        return 0;
    }

    代码二:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    #define MS(a) memset(a,0,sizeof(a))
    #define MP make_pair
    #define PB push_back
    const int INF = 0x3f3f3f3f;
    const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
    inline ll read(){
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    //////////////////////////////////////////////////////////////////////////
    const int maxn = 1e5+10;
    
    int n,q,s,tot;
    int head[maxn];
    
    struct edge{
        int u,v,w,next;
    }e[maxn*2];
    
    void add(int u,int v,int w,int &k){
        e[k].u=u; e[k].v=v; e[k].w=w;
        e[k].next=head[u]; head[u]=k++;
        swap(u,v);
        e[k].u=u; e[k].v=v; e[k].w=w;
        e[k].next=head[u]; head[u]=k++;
    }
    
    int ver[maxn*2],R[maxn*2],fir[maxn],_pow[25],dis[maxn],dp[maxn*2][25],dep[maxn];
    bool vis[maxn];
    
    void dfs(int u,int d){
        vis[u]=true; ver[++tot]=u, R[tot]=d, fir[u]=tot, dep[u]=d;
        for(int i=head[u]; i!=-1; i=e[i].next){
            int v=e[i].v,w=e[i].w;
            if(vis[v]) continue;
            dis[v] = dis[u]+w;
            dfs(v,d+1);
            ver[++tot]=u,R[tot]=d;
        }
    }
    
    void ST(int len){
        int k = (int)(log(len*1.0)/log(2.0));
        for(int i=0; i<=len; i++) dp[i][0] = i;
        for(int j=1; j<=k; j++){
            for(int i=1; i+(1<<j)-1<=len; i++){
                int a = dp[i][j-1], b = dp[i+_pow[j-1]][j-1];
                if(R[a] < R[b]) dp[i][j] = a;
                else dp[i][j] = b;
            }
        }
    }
    int RMQ(int x,int y){
        int k = (int)(log((y-x+1)*1.0)/log(2.0));
        int a = dp[x][k], b = dp[y-_pow[k]+1][k];
        if(R[a] < R[b]) return a;
        else return b;
    }
    int LCA(int x,int y){
        int a = fir[x], b = fir[y];
        if(a > b) swap(a,b);
        int res = RMQ(a,b);
        return ver[res];
    }
    
    void change(int u,int f,int x){
        dis[u] += x;
        for(int i=head[u]; i!=-1; i=e[i].next){
            int v = e[i].v;
            if(v == f) continue;
            change(v,u,x);
        }
    }
    
    int main(){
        for(int i=0; i<25; i++) _pow[i] = (1<<i);
        while(cin>>n>>q>>s){
            tot = 0;
            memset(head,-1,sizeof(head));
            for(int i=1; i<n; i++){
                int u,v,w; scanf("%d%d%d",&u,&v,&w);
                add(u,v,w,tot);
            }
            tot = 0;
            MS(dis); MS(vis);
            dfs(1,1);
            ST(tot);
            while(q--){
                int op = read();
                if(op == 0){
                    int v = read();
                    int ans = dis[s]+dis[v]-2*dis[LCA(s,v)];
                    s = v;
                    cout << ans << endl;
                }else{
                    int x,y; scanf("%d%d",&x,&y);
                    int t = (x-1)*2;
                    int u = e[t].u, v = e[t].v, w = e[t].w;
                    int t1 = dep[u]>dep[v] ? u:v;
                    int t2 = dep[u]>dep[v] ? v:u;
                    e[t].w = e[t^1].w = y;
                    change(t1,t2,y-w);
                }
            }
        }
    
        return 0;
    }
  • 相关阅读:
    指针的引用
    引用的基础知识
    const的基础用法
    解决'fopen':this function or variable may be unsafe先关问题的方法
    C++类中不写成员函数易犯错模型
    PCB接地设计宝典:ADI资深专家总结的良好接地指导原则
    电路板级的电磁兼容性设计
    自然对流仿真设置
    Pspice 原理图以及仿真图 输出到 word
    信号完整性常见问题
  • 原文地址:https://www.cnblogs.com/yxg123123/p/7468021.html
Copyright © 2011-2022 走看看