zoukankan      html  css  js  c++  java
  • BZOJ 3040最短路

    题目描述

    给定一个 NN 个点, MM 条有向边的带权图,请你计算从 SS 出发,到每个点的距离。

    数据保证你能从 SS 出发到任意点。

    输入输出格式

    输入格式:

     

    第一行两个整数 NN 、 MM ,表示点数和边数。 第二行六个整数 TT 、 rxarxa 、 rxcrxc 、 ryarya 、 rycryc 、 rprp 。

    前 TT 条边采用如下方式生成:

    1. 初始化 x=y=z=0x=y=z=0 。
    2. 重复以下过程 TT 次:
      x=(x*rxa+rxc)%rp;
      y=(y*rya+ryc)%rp;
      a=min(x%n+1,y%n+1);
      b=max(y%n+1,y%n+1);

      则有一条从 aa 到 bb 的,长度为 1e8-100*a1e8100a 的有向边。

    后 M-TMT 条边采用读入方式: 接下来 M-TMT 行每行三个整数 x,y,zx,y,z ,表示一条从 xx 到 yy 长度为 zz 的有向边。

     

    输出格式:

     

    一个整数,表示 11 到 NN 的最短路。

     

    输入输出样例

    输入样例#1: 
    3 3
    0 1 2 3 5 7
    1 2 1
    1 3 3
    2 3 1
    输出样例#1: 
    2

    说明

    1leq Nleq 10^61N106 , 1leq Mleq 10^71M107

    1leq x,yleq N1x,yN , 0<z,rxa,rxc,rya,ryc,rp<2^{31}0<z,rxa,rxc,rya,ryc,rp<231

    请采用高效的堆来优化Dijkstra算法。

    Solution:

      本题实在是毒瘤,而且内存限制还卡的那么死。

      思路还是比较正常的堆优化dijkstra,只不过我们用的是更高效的配对堆(pbds中的配对堆)。

      然后坑点就是空间很死,为了防止重复入队,我们记录一下堆中每个元素的迭代器,然后在三角不等式更新后直接判断该节点是否已在堆中,若在就直接modify修改值,否则才入队,这样能保证堆中元素不超过$N$。

    代码:

    #include<bits/stdc++.h>
    #include<ext/pb_ds/assoc_container.hpp>
    #include<ext/pb_ds/priority_queue.hpp>
    #define il inline
    #define ll long long
    #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
    using namespace std;
    using namespace __gnu_pbds;
    const int N=1000005,M=10000000;
    const ll inf=100000000000000000;
    int n,m,s,to[M+5],w[M+5],h[N],net[M+5],cnt;
    ll dis[N];
    int T,rxa,rxc,rya,ryc,rp;
    bool vis[N];
    struct node{
        int u;ll d;
        node(int a=0,ll b=0){u=a,d=b;}
        bool operator<(const node &a)const {return d>a.d;}
    };
    typedef __gnu_pbds::priority_queue<node,less<node>,pairing_heap_tag> heap;
    
    heap q;
    heap::point_iterator id[N];
    
    il int gi(){
        int a=0;char x=getchar();
        while((x<'0'||x>'9')&&x!='-')x=getchar();
        while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,x=getchar();
        return a;
    }
    
    il void add(int u,int v,int c){to[++cnt]=v,net[cnt]=h[u],h[u]=cnt,w[cnt]=c;}
    
    il void spfa(){
        For(i,2,n) dis[i]=inf;
        dis[s]=0,q.push(node(s,0));
        while(!q.empty()){
            node x=q.top();q.pop();
            int u=x.u;
            if(vis[u])continue;
            vis[u]=1;
            for(int i=h[u];i;i=net[i])
                if(dis[to[i]]>dis[u]+w[i]){
                    dis[to[i]]=dis[u]+w[i];
                    if(id[to[i]]==0)id[to[i]]=q.push(node(to[i],dis[to[i]]));
                    else q.modify(id[to[i]],node(to[i],dis[to[i]]));
                }
        }
    }
    
    int main(){
        n=gi(),m=gi(),T=gi(),rxa=gi(),rxc=gi(),rya=gi(),ryc=gi(),rp=gi(),s=1;
        ll x=0,y=0,z=0,a,b;
        m-=T;
        For(i,1,T){
            x=(x*rxa+rxc)%rp,
            y=(y*rya+ryc)%rp,
            a=min(x%n+1,y%n+1),
            b=max(y%n+1,y%n+1);
            add(a,b,100000000-100*a);
        }
        For(i,1,m) x=gi(),y=gi(),z=gi(),add(x,y,z);
        spfa();
        cout<<dis[n];
        return 0;
    }
  • 相关阅读:
    CentOS6.5配置MySQL主从同步
    CentOS6.5安装telnet
    linux 下安装Google Chrome (ubuntu 12.04)
    jdk w7环境变量配置
    JDBCConnectionException: could not execute query,数据库连接池问题
    注意开发软件的版本问题!
    linux mysql命令行导入导出.sql文件 (ubuntu 12.04)
    linux 下root用户和user用户的相互切换 (ubuntu 12.04)
    linux 下 vim 的使用 (ubuntu 12.04)
    linux 下安装配置tomcat-7 (ubuntu 12.04)
  • 原文地址:https://www.cnblogs.com/five20/p/9360838.html
Copyright © 2011-2022 走看看