BZOJ3040: 最短路(road)

题解: 裸最短路 存一下手写堆优化的dij的板子

#include <bits/stdc++.h>
#define ll long long
#define link(x) for(edge *j=h[x];j;j=j->next)
const int NM=1e7+10;
const int nm=1e6+10;
const ll inf=9e18;
using namespace std;
struct FastIO
{
    static const int S=200;
    int wpos;
    char wbuf[S];
    FastIO():wpos(0){}
    inline int xchar()
    {
        static char buf[S];
        static int len=0,pos=0;
        if(pos==len) pos=0,len=fread(buf,1,S,stdin);
        if(pos==len) exit(0);
        return buf[pos++];
    }
    inline int read()
    {
        int s=1,c=xchar(),x=0;
        while(c<=32) c=xchar();
        if(c=='-') s=-1,c=xchar();
        for(;'0'<=c&&c<='9';c=xchar()) x=x*10+c-'0';
        return x*s;
    }
    ~FastIO()
    {
        if(wpos) fwrite(wbuf,1,wpos,stdout),wpos=0;
    }
}io;
struct edge{int t;ll vul;edge*next;}e[NM],*h[nm],*o=e;
void add(int x,int y,ll vul){o->t=y;o->vul=vul;o->next=h[x];h[x]=o++;}
int n,m,t;
int rxa,rxc,rya,ryc,rp,x,y,z;ll dis[nm];
struct Heap{
	int num[nm],pos[nm],size;
	
	void PushUp(int p) {
		while(p > 1) {
			if(dis[num[p]] < dis[num[p >> 1]]) {
				swap(num[p],num[p >> 1]);
				swap(pos[num[p]],pos[num[p >> 1]]);
				p >>= 1;
			}
			else break;
		}
	}
	void Insert(long long x) {
		num[++size] = x;
		pos[x] = size;
		PushUp(size);
	}
	void Pop() {
		pos[num[1]] = 0;
		num[1] = num[size--];
		if(size) pos[num[1]] = 1;
		int now = 2;
		while(now < size) {
			if(dis[num[now + 1]] < dis[num[now]])
				++now;
			if(dis[num[now]] < dis[num[now >> 1]]) {
				swap(num[now],num[now >> 1]);
				swap(pos[num[now]],pos[num[now >> 1]]);
				now <<= 1;
			}
			else break;
		}
	}
}heap;
void dij(int p){
	for(int i=1;i<=n;i++)dis[i]=inf,heap.Insert(i);
	dis[p]=0;
	while(heap.size){
		int t1=heap.num[1];heap.Pop();
		link(t1){
			if(dis[j->t]>dis[t1]+j->vul){
				dis[j->t]=dis[t1]+j->vul;
				heap.PushUp(heap.pos[j->t]);
			}
		}
	}
}
int main(){
	n=io.read();m=io.read();
	t=io.read();rxa=io.read();rxc=io.read();rya=io.read();ryc=io.read();rp=io.read();
	x=0;y=0;z=0;int u,v;int vul;
	for(int i=1;i<=t;i++){
		x=(1LL*x*rxa+rxc)%rp;y=(1LL*y*rxa+rxc)%rp;
		u=min(x%n+1,y%n+1);v=y%n+1;vul=100000000-100*u;
		if(u!=v)add(u,v,vul);
	}
	for(int i=1;i<=m-t;i++)u=io.read(),v=io.read(),vul=io.read(),add(u,v,vul);
	dij(1);
	printf("%lld\n",dis[n]);
	return 0;
}	

 

3040: 最短路(road)

Time Limit: 60 Sec  Memory Limit: 200 MB
Submit: 4153  Solved: 1335
[Submit][Status][Discuss]

Description

N个点,M条边的有向图,求点1到点N的最短路(保证存在)。
1<=N<=1000000,1<=M<=10000000

Input


第一行两个整数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

Output


一个整数,表示1~N的最短路。

Sample Input

3 3
0 1 2 3 5 7
1 2 1
1 3 3
2 3 1

Sample Output

2

HINT

【注释】

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

posted @ 2018-08-15 01:44  wang9897  阅读(228)  评论(0编辑  收藏  举报