Dijkstra求最短路。
这题用普通的手写堆还过不了。。
考虑更新一个堆中的元素时,普通的优先队列是再push一个进去,但是手写堆就不需要这样,只要找到这个元素在堆中位置再尝试向上交换就行了,代码中就是update函数。别的pop(),top()之类操作和普通堆都差不多。最开始要把所有元素放进堆里。
由于每次还要找到一个元素在堆中的位置,所以用index[]数组记录,交换堆中的元素时切记也要交换index[]数组!!!由于index好像重名所以代码中用了define。
#include<bits/stdc++.h>
#define lson (x<<1)
#define rson (x<<1|1)
#define ll long long
#define index ind
using namespace std;
const int N=1000001;
const int M=N*10;
const ll INF=1e18;
int n,m;
int T,rxa,rxc,rya,ryc,rp;
int cnt,Next[M],head[N],v[M],w[M];
ll dis[N];
int h[N],index[N];
int L;
bool b[N];
inline void read(int &x){
char ch=getchar();x=0;
for(;ch<'0'||ch>'9';ch=getchar());
for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
}
inline void read(ll &x){
char ch=getchar();x=0;
for(;ch<'0'||ch>'9';ch=getchar());
for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
}
inline void add(ll x,ll y,ll z){
Next[++cnt]=head[x];
head[x]=cnt;
v[cnt]=y;
w[cnt]=(int) z;
}
void Swap(int x,int y){
swap(index[h[x]],index[h[y]]);
swap(h[x],h[y]);
}
void update(int u){
int x=index[u];
while(x>1&&dis[h[x]]<dis[h[x>>1]]){
Swap(x,x>>1);
x>>=1;
}
}
int top(){
return h[1];
}
void pop(){
h[1]=h[L--];
index[h[1]]=1; //就是少写了这一句呜呜呜
h[L+1]=0;
int x=1;
while(rson<=L){
if (dis[h[x]]<=dis[h[lson]]&&dis[h[x]]<=dis[h[rson]]) break;
int w=0;
if (dis[h[lson]]<dis[h[rson]]) w=lson;
else w=rson;
Swap(w,x);
x=w;
}
if (lson<=L&&dis[h[lson]]<dis[h[x]]) Swap(lson,x);
}
inline void dijk(){
for(int i=1;i<=n;++i){
int x=top();
pop();
b[x]=1;
for(int j=head[x];j!=-1;j=Next[j])
if (!b[v[j]]&&dis[x]+w[j]<dis[v[j]]){
dis[v[j]]=dis[x]+w[j];
update(v[j]);
}
}
}
int main(){
memset(head,-1,sizeof head);
read(n);read(m);
read(T);read(rxa);read(rxc);read(rya);read(ryc);read(rp);
ll x=0,y=0,z=0;
ll a,b;
for(int i=1;i<=T;++i){ //这一段是生成数据不用管
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,1e8-100*a);
}
for(int i=T+1;i<=m;++i){
read(x);read(y);read(z);
add(x,y,z);
}
memset(dis,0x3f,sizeof dis);
dis[1]=0;
for(int i=1;i<=n;i++){ //将元素放进堆里
h[++L]=i;
index[i]=i;
}
dijk();
if (dis[n]>1e17) cout<<"-1"<<endl;else cout<<dis[n]<<endl;
return 0;
}
一开始看到题目还以为是个大水题。。
mdzz调了我两天因为少写了一句交换序号。。拍了30+万组数据才拍出来。。
不知道517从哪里搞来的题 517好像把这题撤了(可能是由于他自己写T了。。)