先来看一道题:
3040: 最短路(road)
众所周知最短路的复杂度是(
m+nlogn
m
+
n
l
o
g
n
)的,但是我们平时的写法实际上是(
m+mlogm
m
+
m
l
o
g
m
)。这样的话我们需要引进一种新的堆:可以修改堆里的值。配对堆满足了我们的需求。
配对堆是一棵树,保证自己比祖先大,不满足二叉。
操作:
1.插入:比较插入和根,哪个大哪个在上面。
2.合并:同插入。
3.取最小:输出根。
4.修改成更小的:把子树取出来,修改,再合并。
5.删除:删除父节点,儿子两两合并再按顺序合并(保证复杂度)。
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
using namespace std;
namespace paring{
#define L 0
#define R 1
struct lxy{
int son[2],fa;
long long num;
}b[1000005];
int root,size;
bool empty(){
return size==0;
}
void merge(int x,int y){
if(b[x].num<b[y].num) swap(x,y);
b[x].son[R]=b[y].son[L];
b[b[x].son[R]].fa=x;
b[y].son[L]=x;
b[x].fa=y;root=y;
}
void push(int u,long long x){
b[u].num=x;size++;
if(size==1) {root=u;return;}
merge(root,u);
}
int top(){return root;}
void modify(int u,long long x){
b[u].num=x;
if(u==root) return;
if(b[b[u].fa].son[L]==u){
b[b[u].fa].son[L]=b[u].son[R];
if(b[u].son[R]!=0) b[b[u].son[R]].fa=b[u].fa;
b[u].son[R]=0;b[u].fa=0;
}
else if(b[b[u].fa].son[R]==u){
b[b[u].fa].son[R]=b[u].son[R];
if(b[u].son[R]!=0) b[b[u].son[R]].fa=b[u].fa;
b[u].son[R]=0;b[u].fa=0;
}
merge(root,u);
}
void pop(){
size--;int f=0;
if(size==0) {root=0;return;}
queue <int> d;stack<int> z;
for(int i=b[root].son[L];i!=0;i=b[i].son[R]) d.push(i),f++;
b[root].son[L]=0;b[root].son[R]=0;b[root].fa=0;b[root].num=0;
while(f>1){
int x,y;
x=d.front();d.pop();y=d.front();d.pop();f-=2;
b[x].son[R]=0;b[x].fa=0;b[y].son[R]=0;b[y].fa=0;
merge(x,y);z.push(root);
}
if(f==1) root=d.front();
else root=z.top(),z.pop();
while(!z.empty()){
merge(root,z.top());
z.pop();
}
}
}
struct lxy{
int to,next;
long long len;
}eg[10000005];
int n,m,s,cnt,a1,a2;
int head[1000005],vis[1000005];
long long dis[1000005];
long long T,rxa,rxc,rya,ryc,rp,x,y,z,a3;
void add(int op,int ed,long long len){
eg[++cnt].next=head[op];
eg[cnt].to=ed;
eg[cnt].len=len;
head[op]=cnt;
}
void spfa(){
memset(dis,0x7f,sizeof(dis));
paring::push(s,0);
dis[s]=0;vis[s]=1;
while(!paring::empty()){
int now=paring::top();paring::pop();
for(int i=head[now];i!=-1;i=eg[i].next)
if(dis[eg[i].to]>dis[now]+eg[i].len){
dis[eg[i].to]=dis[now]+eg[i].len;
if(vis[eg[i].to]==1) paring::modify(eg[i].to,dis[eg[i].to]);
else paring::push(eg[i].to,dis[eg[i].to]),vis[eg[i].to]=1;
}
}
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);s=1;
scanf("%lld%lld%lld%lld%lld%lld",&T,&rxa,&rxc,&rya,&ryc,&rp);
for(int i=1;i<=T;i++){
x=(x*rxa+rxc)%rp;
y=(y*rya+ryc)%rp;
a1=min(x%n+1,y%n+1);
a2=max(y%n+1,y%n+1);
add(a1,a2,100000000-100*a1);
}
for(int i=T+1;i<=m;i++){
scanf("%d%d%lld",&a1,&a2,&a3);
add(a1,a2,a3);
}
spfa();
printf("%lld",dis[n]);
}
8963

被折叠的 条评论
为什么被折叠?



