题目描述

给定一个 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

说明

1\leq N\leq 10^61N106 , 1\leq M\leq 10^71M107

1\leq x,y\leq 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;
}