• NOI2018 归程


    题目链接:戳我

    kruskal重构树做法。
    预处理每个点到根的最短路。
    将边从大到小排序,然后建树,建出来的kruskal生成树就是一个小根堆。

    我们尽可能的从当前点向上面跳。(也就是带限制“海拔大于等于p”的树上倍增)
    然后呢,因为是一个小根堆,我们可以免费走到该点子树以内任意一个点,所以我们来一个dfs找出字数内到1最短路最短的答案即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define MAXN 400010
    using namespace std;
    int t,n,m,tt,tt2,Q,K,S,v0,p0,cnt,lastans;
    int dist[MAXN],done[MAXN],head[MAXN<<1],head2[MAXN<<1],fa[MAXN<<1],g[MAXN][22],dep[MAXN];
    struct Line{int u,v,len,h;}line[MAXN];
    struct Node{
        int u,d;
        friend bool operator <(struct Node x,struct Node y)
        {return x.d>y.d;}
    }node[MAXN<<1];
    struct Edge{int nxt,to,dis,hei;}edge[MAXN<<2],e[MAXN<<2];
    struct Node2{int u,v,l,a;}kkk[MAXN<<2];
    inline void add(int from,int to,int dis)
    {
        edge[++tt].nxt=head[from],edge[tt].to=to,edge[tt].dis=dis,head[from]=tt;
    }
    inline void add2(int from,int to){e[++tt2].nxt=head2[from],e[tt2].to=to,head2[from]=tt2;}
    inline bool cmp(struct Line x,struct Line y){return x.h>y.h;}
    inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    inline void dij(int s)
    {
        priority_queue<Node>q;
        memset(done,0,sizeof(done));
        memset(dist,0x3f,sizeof(dist));
        q.push((Node){s,0});dist[s]=0;
        while(!q.empty())
        {
            int u=q.top().u;q.pop();
            if(done[u]) continue;
            done[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int v=edge[i].to;
                if(dist[u]+edge[i].dis<dist[v])
                    dist[v]=dist[u]+edge[i].dis,q.push((Node){v,dist[v]});
            }
        }
        for(int i=1;i<=n;i++) kkk[i].l=dist[i];
    }
    inline void kruskal()
    {
        for(int i=1;i<=n*2;i++) fa[i]=i;
        sort(&line[1],&line[m+1],cmp);
        int tot=0;
        cnt=n;
        for(int i=1;i<=m;i++)
        {
            int u=line[i].u,v=line[i].v;
            int a=find(u),b=find(v);
            if(a!=b) 
            {
                cnt++;
                fa[a]=cnt,fa[b]=cnt,fa[cnt]=cnt;
                //printf("u=%d v=%d a=%d b=%d 长度=%d 海拔=%d cnt=%d
    ",u,v,a,b,line[i].len,line[i].h,cnt);
                add2(cnt,a);add2(cnt,b);
                kkk[cnt].a=line[i].h;
                tot++;
            }
            if(tot==n-1) break;
        }
    }
    inline void dfs(int x,int pre)
    {
        dep[x]=dep[pre]+1;
        g[x][0]=pre;
        for(int i=1;i<=21;i++) g[x][i]=g[g[x][i-1]][i-1];
        for(int i=head2[x];i;i=e[i].nxt)
        {
            int v=e[i].to;
            dfs(v,x);
            kkk[x].l=min(kkk[x].l,kkk[v].l);
        }
    }
    inline int query(int x,int y){
        for(int i=21;i>=0;--i)
            if(dep[x]-(1<<i)>0&&kkk[g[x][i]].a>y)
                x=g[x][i];
        return kkk[x].l;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&t);
        while(t--)
        {
            memset(fa,0,sizeof(fa));
            memset(head,0,sizeof(head));
            memset(head2,0,sizeof(head2));
            tt=tt2=lastans=0;
            scanf("%d%d",&n,&m);
            for(int i=1;i<=m;i++) 
            {   
                scanf("%d%d%d%d",&line[i].u,&line[i].v,&line[i].len,&line[i].h);
                add(line[i].u,line[i].v,line[i].len),add(line[i].v,line[i].u,line[i].len);
            }
            for(int i=n+1;i<=2*n;i++) kkk[i].l=0x3f3f3f3f;
            dij(1);
            kruskal();
            dfs(cnt,0);
            scanf("%d%d%d",&Q,&K,&S);
            for(int i=1;i<=Q;i++)
            {
                scanf("%d%d",&v0,&p0);
                int v=(v0+K*lastans-1)%n+1;
                int p=(p0+K*lastans)%(S+1);
                lastans=query(v,p);
                printf("%d
    ",lastans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    【Opencv】直方图函数 calchist()
    【Lintcode】070.Binary Tree Level Order Traversal II
    【C++】*p++ = *p不同环境下操作不同
    【Python】String 字符串
    【Python】File IO
    栈和队列
    链表
    printf 的格式
    Linux的基本指令--
    机器人的运动范围
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10359135.html
Copyright © 2020-2023  润新知