• SDOI2015寻宝游戏 dfs序+set


    SDOI2015寻宝游戏

    好像是一道虚树入门题?

    虚树???不会不会我弱死了。。

    Solution:

    关键点间的最小路径,就是在保证尽量少走重复路的前提下走出来的一条经过所有关键点的路径。

    基于这个思想,我们思考怎样走出来的会是重复最少的呢???

    不妨想一想dfs,我们dfs时就是保证了每个点只遍历一次,每条边只遍历了两次,这已经是最优的情况了!!

    所以,对于这些关键点,把它们按照dfs序遍历,可以发现路径就是最小的。

    对于修改,我们相当于只要维护了关键点dfs序,就只要对应的在序列上插入、删除就好了,用set即可。

    说实话,本人运用set等STL的能力极差,所以每每遇到这种需要set等的题,就会。。。enenen

    Code↓:

    #include<set>
    #include<cmath>
    #include<string>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define RG register
    #define IL inline
    #define LL long long
    #define DB double 
    using namespace std;
    
    IL int gi() {
        char ch=getchar(); RG int x=0,q=0;
        while(ch<'0'||ch>'9') q=ch=='-'?1:q,ch=getchar();
        while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return q?-x:x;
    }
    
    const int N=1e5+10;
    
    set<int> seq;
    set<int>::iterator IT,pr,sf;
    
    LL ans,dis[N];
    int n,m,Time,tot,head[N],mp[N],dep[N],dfn[N],dot[N],f[N][21];
    
    struct EDGE{int next,to,ver;}e[N<<1];
    IL void make(int a,int b,int c) {
        e[++tot]=(EDGE){head[a],b,c},head[a]=tot;
        e[++tot]=(EDGE){head[b],a,c},head[b]=tot;
    }
    
    void dfs(int x,int fx) {
        RG int i,y;
        dfn[x]=++Time,mp[Time]=x;
        for (i=head[x],dep[x]=dep[fx]+1;i;i=e[i].next)
            if ((y=e[i].to)!=fx) f[y][0]=x,dis[y]=dis[x]+e[i].ver,dfs(y,x); 
    }
    
    IL void getf() {
        RG int i,j;
        for (i=1;i<=18;++i)
            for (j=1;j<=n;++j)
                f[j][i]=f[f[j][i-1]][i-1];
    }
    
    IL void Find(int x) {
        IT=seq.lower_bound(dfn[x]);
        if (IT==seq.begin()) pr=seq.end(),pr--;
        else pr=IT,pr--;
        sf=IT,sf++;
        if (sf==seq.end()) sf=seq.begin();
    }
    
    IL int Lca(int x,int y) {
        RG int i;
        if (dep[x]<dep[y]) swap(x,y);
     	for (i=18;i>=0;--i)
            if (dep[f[x][i]]>=dep[y]) x=f[x][i];
        if (x==y) return x;
        for (i=18;i>=0;--i)
            if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    
    IL LL Path(int x,int y) {return dis[x]+dis[y]-2*dis[Lca(x,y)];}
    
    int main ()
    {
        RG int i,x,y,z,pre=0,suf=0;
        n=gi(),m=gi();
        for (i=1;i<n;++i) x=gi(),y=gi(),z=gi(),make(x,y,z);
        for (i=1,dfs(1,0),getf();i<=m;++i) {
            dot[x=gi()]^=1;
            if (dot[x]) {
                seq.insert(dfn[x]),Find(x);
                suf=mp[*sf],pre=mp[*pr];
                ans+=Path(pre,x)+Path(x,suf)-Path(pre,suf);
            }
            else {
                Find(x),seq.erase(dfn[x]);
                suf=mp[*sf],pre=mp[*pr];
                ans+=Path(pre,suf)-Path(pre,x)-Path(x,suf);
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
    

    The End

  • 相关阅读:
    Linux发行版 CentOS6.5 修改默认主机名
    《Linux就该这么学》培训笔记_ch06_存储结构与磁盘划分
    《Linux就该这么学》培训笔记_ch05_用户身份与文件权限
    《Linux就该这么学》培训笔记_ch04_Vim编辑器与Shell命令脚本
    《Linux就该这么学》培训笔记_ch03_管道符、重定向与环境变量
    《Linux就该这么学》培训笔记_ch02_一些必须掌握的Linux命令
    《Linux就该这么学》培训笔记_ch01_部署虚拟环境安装Linux系统
    《Linux就该这么学》培训笔记_ch00_认识Linux系统和红帽认证
    Swift笔记2
    request对象和response对象
  • 原文地址:https://www.cnblogs.com/Bhllx/p/10616998.html
Copyright © 2020-2023  润新知