zoukankan      html  css  js  c++  java
  • BZOJ3991 [SDOI2015] 寻宝游戏

    @(XSY)[DFS序]

    Description

    小B最近正在玩一个寻宝游戏,这个游戏的地图中有(N)个村庄和(N - 1)条道路,并且任何两个村庄之间有且仅有一条路径可达。游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走,若走到某个村庄中有宝物,则视为找到该村庄内的宝物,直到找到所有宝物并返回到最初转移到的村庄为止。小B希望评测一下这个游戏的难度,因此他需要知道玩家找到所有宝物需要行走的最短路程。但是这个游戏中宝物经常变化,有时某个村庄中会突然出现宝物,有时某个村庄内的宝物会突然消失,因此小B需要不断地更新数据,但是小B太懒了,不愿意自己计算,因此他向你求助。为了简化问题,我们认为最开始时所有村庄内均没有宝物

    Input

    第一行,两个整数(N)(M),其中(M)为宝物的变动次数。
    接下来的(N - 1)行,每行三个整数(x)(y)(z),表示村庄(x)(y)之间有一条长度为(z)的道路。
    接下来的(M)行,每行一个整数(t),表示一个宝物变动的操作。若该操作前村庄t内没有宝物,则操作后村庄内有宝物;若该操作前村庄t内有宝物,则操作后村庄内没有宝物。

    Output

    M行,每行一个整数,其中第i行的整数表示第i次操作之后玩家找到所有宝物需要行走的最短路程。若只有一个村庄内有宝物,或者所有村庄内都没有宝物,则输出0。

    Sample Input

    4 5
    1 2 30
    2 3 50
    2 4 60
    2
    3
    4
    2
    1
    

    Sample Output

    0
    100
    220
    220
    280
    

    HINT

    (1 le N le 100000)
    (1 le M le 100000)
    对于全部的数据,(1 le z le 10^9)

    Solution

    預處理出每個點的dfs序.
    對於每個操作, 用set维护dfs序。

    题意大概就是要求动态维护一些树链的并的长度。
    我们可以发现要求的路径类似于一个“章鱼”的样子,我们可以求出dfs序相邻的两两之间的路径长度,再加上Dfs序最靠前和dfs序最靠后的之间的路径长度就是答案.

    可以直接看個代碼:

    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <set>
    #define LL long long
    #define M 100005
    using namespace std;
    set<int> s;
    set<int>:: iterator it;
    int d[M],id[M],v[M],w[M],now=0,tot=0,h[M],n,m;
    int f[100005][25];
    LL ans,pre[M];
    struct edge
    {
        int x,y,ne;
        LL v;
    }e[M*3];
    void Addedge(int x,int y,LL v)
    {
        e[++tot].y=y;
        e[tot].ne=h[x];
        e[tot].v=v;
        h[x]=tot;
    }
    void read(int &tmp)
    {
        tmp=0;
        char ch=getchar();
        for (;ch<'0'||ch>'9';ch=getchar());
        for (;ch>='0'&&ch<='9';ch=getchar())
            tmp=tmp*10+ch-'0';
    }
    void dfs(int x,int fa,int dep)
    {
        f[x][0]=fa;
        w[id[x]=++now]=x;
        d[x]=dep;
        for (int i=h[x];i;i=e[i].ne)
        {
            int y=e[i].y;
            if (y==fa) continue;
            pre[y]=pre[x]+e[i].v;
            dfs(y,x,dep+1);
        }
    }
    void ST()
    {
        for (int j=1;j<=20;j++)
            for (int i=1;i<=n;i++)
                f[i][j]=f[f[i][j-1]][j-1];
    }
    void Move(int &x,int dep)
    {
        for (int i=20;i>=0;i--)
            if (d[f[x][i]]>=dep)
                x=f[x][i];
    }
    int Getlca(int x,int y)
    {
        if (d[x]>d[y]) swap(x,y);
        if (d[x]!=d[y])
            Move(y,d[x]);
        if (x==y) return x;
        for (int i=20;i>=0;i--)
            if (f[x][i]!=f[y][i])
                x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    LL dis(int x,int y)
    {
        return pre[x]+pre[y]-pre[Getlca(x,y)]*2;
    }
    int ne(int x)
    {
        it=s.find(id[x]);
        return ++it==s.end()?0:w[*it];
    }
    int pr(int x)
    {
        it=s.find(id[x]);
        return it==s.begin()?0:w[*--it];
    }
    void Add(int x)
    {
        s.insert(id[x]);
        int l=pr(x),r=ne(x);
        if (l) ans+=dis(l,x);
        if (r) ans+=dis(x,r);
        if (l&&r) ans-=dis(l,r);
    }
    void Erase(int x)
    {
        int l=pr(x),r=ne(x);
        if (l) ans-=dis(l,x);
        if (r) ans-=dis(x,r);
        if (l&&r) ans+=dis(l,r);
        s.erase(id[x]);
    }
    int main()
    {
        read(n),read(m);
        for (int i=1;i<n;i++)
        {
            int x,y;
            LL v;
            scanf("%d%d%lld",&x,&y,&v);
            Addedge(x,y,v),Addedge(y,x,v);
        }
        dfs(1,0,1);
        ST();
        ans=0;
        for (int i=1;i<=m;i++)
        {
            int x;
            read(x);
            if (v[x]) Erase(x);
            else Add(x);
            v[x]^=1;
            printf("%lld
    ",s.size()?ans+dis(w[*s.begin()],w[*--s.end()]):0);
        }
        return 0;
    }
    
  • 相关阅读:
    页面制作 Chapter 3--HTML
    页面制作 Chapter 2--开发、调试工具
    页面制作 Chapter 1--PhotoShop切图笔记
    打开AzureRay园子的大门,欢迎大家串门哟~
    自定义Console.log
    简单事件模型,JS防止单个函数异步重复调用
    C# 调用Restful 请求
    各类开源License说明
    面试JS
    gitignore
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/6424507.html
Copyright © 2011-2022 走看看