Bzoj3040 dijkstra堆优化+链式前向星

Bzoj3040 dijkstra堆优化+链式前向星

问题描述:

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=(xrxa+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

先介绍一下一种新的存图方式:链式前向星

#include<bits/stdc++.h>
using namespace std;
const int MAXV = ;//图中点的最大值
const int MAXN = ;//图中边的最大值
int head[MAXN];//head[u]就代表u为起点的第一条边在edge数组中的下标
int cnt = 0;//cnt 代表当前的所有边的边数
struct EDGE{
    int v;//这条边所指向的顶点
    int next;//下一条边在edge数组中的下标 默认是0
    int w;//边的权值
};
EDGE edge[MAXN];
Add (int x,int y,int w) {//添加边的操作,x->y 权值为w
	edge[++cnt].next = head[x];//逆序添加边,添加的边为head[x]所代表的 
	edge[cnt].v = y;
    edge[cnt].w = w;
    head[x] = cnt;
}
void Print(int u) {//遍历操作,从u顶点开始遍历由该顶点出发的所有边 
	for(int i = head[u];i != 0;i = edge[i].next) {
	printf("%d %d\n",edge[i].v,edge[i].w);
	}
}	

这题如果不用链式前向星存的话会爆内存。。。 当然也有神仙通过配对堆优化来卡过内存 总之简单的使用dijkstra堆优化来写的话就会mle(还有牛逼老哥用斐波那契堆优化过的orz hhhhhh)

当然仅仅用链式前向星的话也是没用的,你还会因为你的优先队列入队太多而re掉(呜呜呜呜这什么神仙题卡了我一整天,归根到底还是我太菜了hhhhhh(这题其实前面的T条边实在假你,因为前面的边对最短路根本没有贡献

ac代码如下:


#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
const int maxm = 1e7 + 5;
const int tt = 1e8;
int n, m, dis[maxn];
int t, rxa, rxc, rya, ryc, rp;
struct edge{
	int to, w, next;
} ed[maxm];
int head[maxn], tot;
bool vis[maxn];
inline void add( int u, int v, int w ){
	ed[++tot].to = v;
	ed[tot].w = w;
	ed[tot].next = head[u];
	head[u] = tot;
}
inline void dij(int beg){
	priority_queue< pair<int, int> > q;
	dis[beg] = 0;
	q.push(make_pair(0, beg));
	while( !q.empty() ){
		int u = q.top().second;
		q.pop();
		if( vis[u] ) continue;
		vis[u] = 1;
		for( int i=head[u]; i!=0; i=ed[i].next ){
			int v = ed[i].to;
			if(vis[v]) continue;
			if( dis[v]>dis[u]+ed[i].w ){
				dis[v] = dis[u]+ed[i].w;
				q.push( make_pair(-dis[v], v) );
			}
		}
	}
}

int main(){
	memset( vis, 0, sizeof(vis) );
	memset( dis, 0x3f, sizeof(dis) );
	tot = 1;
	scanf("%d%d", &n, &m);
	scanf("%d %d %d %d %d %d", &t, &rxa, &rxc, &rya, &ryc, &rp);
	for( int i=0; i<t; i++ ){
		int x, y, a, b, w;
		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);
		w = tt-100*a;
		add( a, b, w );
	}
	for( int i=t; i<m; i++ ){
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		add( u, v, w );
	}
	dij(1);
	printf("%d\n", dis[n]);

	return 0;
}
posted @ 2019-05-28 13:50  Potato!  阅读(200)  评论(0编辑  收藏  举报