问题 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]);
}