问题 A: 最短路
题目描述
N个点,M条边的有向图,求点1到点N的最短路(保证存在)。 1<=N<=1000000,1<=M<=10000000
输入格式
第一行两个整数N、M,表示点数和边数。
第二行六个整数T、rxa、rxc、rya、ryc、rp。
前T条边采用如下方式生成:
1.初始化x=y=z=0。
2.重复以下过程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);
则有一条从a到b的,长度为1e8-100*a的有向边。
后M-T条边采用读入方式:
接下来M-T行每行三个整数x,y,z,表示一条从x到y长度为z的有向边。
1<=x,y<=N,0<z,rxa,rxc,rya,ryc,rp<2^31
输出格式
一个整数,表示1~N的最短路。
输入样例
3 3
0 1 2 3 5 7
1 2 1
1 3 3
2 3 1
输出样例
2
提示
请采用高效的堆来优化Dijkstra算法。
题解
配对堆:https://www.cnblogs.com/Paul-Guderian/p/7664366.html
虽然可以用pb_ds。
但还是手写保险
调了五天+
结果发现自己的配对堆有两个地方没有清零。。。
而且回收边编号的垃圾桶的数组也开小了。。。
自闭了
AC:5505ms(没有注释随机边哦~~)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int gi()
{
char c;int num=0,flg=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flg-=1;
while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}
return num*flg;
}
#define N 1000005
#define M 10000005
#define LL long long
LL dis[N];
struct PH{//Pairing_Heap
int fir[N],to[M],nxt[M],fa[N],rt;// Attention!!!
int trashbin[2*M],tp,stk[2*N],top;// Attention!!!
void csh(int n){
for(tp=2*n;tp>=1;tp--)
trashbin[tp]=tp;
tp=n;rt=0;
}
int merge(int x,int y){
if(dis[x]>dis[y])swap(x,y);fa[y]=x;
int nep=trashbin[tp--];
to[nep]=y;nxt[nep]=fir[x];fir[x]=nep;
return x;
}
void Push(int x){fa[x]=0;rt=(!rt?x:merge(rt,x));}// Attention!!!
int Top(){return rt;}
void Pop(){
top=0;
for(int p=fir[rt];p;p=nxt[p]){
trashbin[++tp]=p;
if(fa[to[p]]==rt){
fa[to[p]]=0;
stk[++top]=to[p];
}
}
fir[rt]=0;// Attention!!!
for(int i=1;i<top;i+=2)
stk[++top]=merge(stk[i],stk[i+1]);
rt=stk[top];
}
}h;
struct enode{int u,v,cd;}e[M];
int fir[N],to[M],cd[M],d[N];
int n,m;
int t;
void Dijk(int s)
{
memset(dis,0x3f,sizeof(dis));
h.csh(m);
dis[h.rt=s]=0;
int u,v,w,i;
while(h.rt){
u=h.Top();h.Pop();
for(i=fir[u]+d[u]-1;i>=fir[u];i--){
v=to[i];w=cd[i];
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
h.Push(v);
}
}
}
}
void adde(int a,int b,int c)
{
to[fir[a]+d[a]]=b;cd[fir[a]+d[a]]=c;d[a]++;
}
int main()
{
int i;
int T,rxa,rxc,rya,ryc,rp,x=0,y=0,z=0,a,b;
n=gi();m=gi();
T=gi();rxa=gi();rxc=gi();rya=gi();ryc=gi();rp=gi();
for(i=1;i<=T;i++){
x=(1ll*x*rxa+1ll*rxc)%rp;y=(1ll*y*rya+1ll*ryc)%rp;
a=min(x%n+1,y%n+1);b=max(x%n+1,y%n+1);
e[i].u=a;e[i].v=b;e[i].cd=100000000-100*a;d[a]++;
}
for(i=T+1;i<=m;i++){
x=gi();y=gi();z=gi();
e[i].u=x;e[i].v=y;e[i].cd=z;d[x]++;
}
int sum=0;
for(i=1;i<=n;i++){fir[i]=sum;sum+=d[i];d[i]=0;}
for(i=1;i<=m;i++) adde(e[i].u,e[i].v,e[i].cd);
Dijk(1);
printf("%lld\n",dis[n]);
}