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;
}

 

posted @ 2017-09-02 21:47  _yxg123  阅读(213)  评论(0编辑  收藏  举报