zoukankan      html  css  js  c++  java
  • Luogu4768 NOI2018归程(最短路径+kruskal重构树)

      按海拔从大到小合并建出kruskal重构树,这样就能知道开车能到达哪些点,对这些点到1的最短路取min即可。最难的部分在于多组数据的初始化和数组大小的设置。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<cassert>
    using namespace std;
    #define ll long long
    #define N 200010
    #define M 400010
    #define inf 2000000010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int T,n,m,p[N],d[N],fa[N<<1],t,cnt;
    bool flag[N];
    struct data{int to,nxt,len,h;
    }edge[M<<1];
    void addedge(int x,int y,int z,int h){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,edge[t].h=h,p[x]=t;}
    struct data2
    {
        int x,d;
        bool operator <(const data2&a) const
        {
            return d>a.d;
        }
    };
    struct data3
    {
        int x,y,z;
        bool operator <(const data3&a) const
        {
            return z>a.z;
        }
    }e[M];
    priority_queue<data2> q;
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    void dijkstra()
    {
        while (!q.empty()) q.pop();q.push((data2){1,0});
        for (int i=2;i<=n;i++) d[i]=inf;d[1]=0;
        memset(flag,0,sizeof(flag));
        for (;;)
        {
            while (!q.empty()&&flag[q.top().x]) q.pop();
            if (q.empty()) break;
            data2 x=q.top();q.pop();
            flag[x.x]=1;
            for (int i=p[x.x];i;i=edge[i].nxt)
            if (x.d+edge[i].len<d[edge[i].to])
            {
                d[edge[i].to]=x.d+edge[i].len;
                q.push((data2){edge[i].to,d[edge[i].to]});
            }
        }
    }
    namespace kruskal_tree
    {
        int p[N<<1],t,fa[N<<1][20],val[N<<1],h[N<<1];
        struct data{int to,nxt,len;}edge[N<<1];
        void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
        void dfs(int k)
        {
            val[k]=k<=n?d[k]:inf;
            for (int i=p[k];i;i=edge[i].nxt)
            {
                fa[edge[i].to][0]=k;
                dfs(edge[i].to);
                val[k]=min(val[k],val[edge[i].to]);
            }
        }
        void build()
        {
            fa[cnt][0]=cnt;dfs(cnt);
            for (int j=1;j<20;j++)
                for (int i=1;i<=cnt;i++)
                fa[i][j]=fa[fa[i][j-1]][j-1];
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("return.in","r",stdin);
        freopen("return.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        T=read();
        while (T--)
        {
            n=read(),m=read();
            for (int i=1;i<=n;i++) p[i]=0;t=0;
            for (int i=1;i<=m;i++)
            {
                int x=read(),y=read(),z=read(),h=read();
                e[i].x=x,e[i].y=y,e[i].z=h;
                addedge(x,y,z,h),addedge(y,x,z,h);
            }
            dijkstra();
            sort(e+1,e+m+1);
            for (int i=1;i<=n;i++) fa[i]=i,kruskal_tree::h[i]=inf,kruskal_tree::p[i]=0;cnt=n;kruskal_tree::t=0;
            for (int i=1;i<=m;i++)
            {
                int p=find(e[i].x),q=find(e[i].y);
                if (p!=q)
                {
                    cnt++;fa[cnt]=fa[p]=fa[q]=cnt;kruskal_tree::p[cnt]=0;
                    kruskal_tree::addedge(cnt,p),kruskal_tree::addedge(cnt,q);
                    kruskal_tree::h[cnt]=e[i].z;
                }
            }
            kruskal_tree::build();
            int Q=read(),K=read(),S=read(),ans=0;
            while (Q--)
            {
                int x=(read()+K*ans-1)%n+1,y=(read()+K*ans)%(S+1);
                for (int j=19;~j;j--) if (kruskal_tree::h[kruskal_tree::fa[x][j]]>y) x=kruskal_tree::fa[x][j];
                printf("%d
    ",ans=kruskal_tree::val[x]);
            }
        }
        return 0;
    }
  • 相关阅读:
    PHP 学习1- 函数之error_reporting(E_ALL ^ E_NOTICE)详细说明
    ja_charity模板研究
    迭代创建级联目录
    迭代和递归的区别
    递归删除目录
    PHP递归仿DOS的tree命令
    深入理解递归
    wamp默认函数嵌套98层,否则报Fatal error: Maximum function nesting level of '100' reached, aborting!
    静态static方法中调运非静态方法
    微信支付05
  • 原文地址:https://www.cnblogs.com/Gloid/p/10177207.html
Copyright © 2011-2022 走看看