zoukankan      html  css  js  c++  java
  • 题解:归程

    我们可以把从v到1的路径分成两部分,一半全开车,一半全走路

    也就是说要枚举n个节点作为断点(假设当前断点为u),这个断点是可行解与最优解当且仅当存:在一条从v到u的路径可以全部开车且从u到1全部走路的最短路是满足上一条件中最短的

    从v出发开车可以到的点, 一定满足路径上所有边海拔都高于水位

    Kruskal重构树:

    这里已经很明显可以用Kruskal重构树求解了

    我们把每条边按海拔降序排序,重构树完成后,对于每次询问,找到树中深度最小且海拔大于水位的节点,那么他的子树的全部节点都可以由v开车到达

    这一点可以由重构树是小根堆的性质简单得证,即每个节点子树内所有节点海拔都比该节点大

    现在要求的最后一步就是这个子树内所有节点到1号节点的步行最短路, 因为是无向图,所以一开始预处理1节点到所有节点最短路就好,然后dfs可以顺便求出某个节点子树内的最短路

    --

    (ps)
    这个题卡 (SPFA) CCF怎么能这样对我可爱的SPFA
    所以必须打迪杰斯特拉


    处理细节:

    1. 莫名卡常(可能是我不优秀),对于一些数组不用清零的就别清了,比如倍增数组和最小值数组(删了HSYOJ就过了)
    2. 克鲁斯卡尔重构树套路:清零!!!(数据不清空,爆零两行泪)

    可持久化并查集

    一定程度上,可持久化并查集的适用范围是大于克鲁斯卡尔重构树的,虽然在这里不是最优秀的做法,把(NlogN)的复杂度硬生生变成了(Nlog^2N)(卡卡常也是能过的),这里虽然不是正解,但也是一个好方案

    做法:

    迪杰斯特拉预处理,然后可持久化并查集维护联通块(口胡完了)

    实现细节:

    注意常数


    代码:

    (这里用的是Kruskal重构树)

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    using namespace std;
    
    #define ll long long
    #define re register
    #define gc getchar()
    inline int read()
    {
        re int x(0),f(1);re char ch(gc);
        while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=gc;}
        while(ch>='0'&&ch<='9') x=(x*10)+(ch^48),ch=gc;
        return x*f;
    }
    
    const int N=8e5+10;
    int h[N],cnt,n,m,f[N][22],tot;
    ll val[N],_min[N],dis[N];
    
    struct edge{int next,to;ll w;}e[N<<1];
    void add(int u,int v,ll w){e[++cnt]=(edge){h[u],v,w},h[u]=cnt;} 
    #define QXX(u) for(int i=h[u],v;v=e[i].to,i;i=e[i].next)
    
    struct node{int u,v;ll h;}E[N<<1];
    bool operator < (node a,node b){return a.h>b.h;}
    
    struct Node{ll x;int id;};
    bool operator < (Node a,Node b){return a.x<b.x;}
    priority_queue <Node> q;
    int vis[N];
    
    int fa[N];
    int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    
    void djs()
    {
        memset(vis,0,sizeof(vis));
        memset(dis,127,sizeof(dis));
        q.push((Node){0,1});
        dis[1]=0;
        while(!q.empty())
        {
            Node t=q.top();q.pop();
            int u=t.id;
            if(vis[u]) continue;
            vis[u]=1;
            QXX(u)
                if(dis[u]+e[i].w<dis[v])
                {
                    dis[v]=dis[u]+e[i].w;
                    q.push((Node){-dis[v],v});
                }
            
        }
    }
    void dfs(int u)
    {
        _min[u]=dis[u];
        QXX(u)
        {
            f[v][0]=u;
            dfs(v);
            _min[u]=min(_min[u],_min[v]);
        }
    }
    void kruskal()
    {
        memset(h,0,sizeof(h));
        cnt=0;
        sort(E+1,E+1+m);
        for(int i=1;i<=n;++i) fa[i]=i;
        for(int i=1;i<=m;++i)
        {
            int u=find(E[i].u),v=find(E[i].v);
            if(u!=v)
            {
                val[++tot]=E[i].h;
                fa[u]=fa[v]=fa[tot]=tot;
                add(tot,u,0),add(tot,v,0);
            }
        }
        dfs(tot);
    }
    int main()
    {
    //	freopen("return.in","r",stdin);
        int T=read();
        while(T--)
        {
            memset(h,0,sizeof(h));
            memset(f,0,sizeof(f));
            memset(_min,127,sizeof(_min));
            n=read(),m=read(),cnt=0;tot=n;
            for(int i=1;i<=m;++i)
            {
                re int u=read(),v=read(),w=read(),h=read();
                add(u,v,w),add(v,u,w);
                E[i].u=u,E[i].v=v,E[i].h=h;
            }
            djs();
            kruskal();
            for(int i=1;(1<<i)<=tot;i++)
                for(int u=1;u<=tot;u++)
        		    f[u][i]=f[f[u][i-1]][i-1];
        	int Q=read(),K=read(),S=read();
            ll la=0;
            while(Q--) 
            {
                int vi=read(),pi=read();
                vi=(vi+K*la-1)%n+1;
                pi=(pi+K*la)%(S+1);
                for(int j=21;j>=0;--j)
                    if(f[vi][j]&&val[f[vi][j]]>pi) 
        		        vi=f[vi][j];
        		la=_min[vi];
        		cout<<la<<endl;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    c# 类中使用ResolveUrl
    IIS7日志中时间与系统时间不一致的原因
    IIS日志-网站运维的好帮手
    精通 JS正则表达式
    word 标题序号
    rtx 二次开发,查找所有部门
    【云计算】Docker容器时间同步如何配置?
    【云计算】Docker多进程管理方案-cfengine && supervisord
    【Python】装饰器实现日志记录
    【云计算】k8s相关资料
  • 原文地址:https://www.cnblogs.com/zijinjun/p/10959703.html
Copyright © 2011-2022 走看看