迪杰斯特拉 Dijkstra
模板(priority_queue)
// T must define < and +
// V: max number of vertex [0~V-1]
template<typename T,size_t V,bool Directed=true,
T INF=T(0x3f3f3f3f),T ZERO=T(0)>
struct G {
typedef pair<T,int> PTI;
vector<PTI> g[V];
T dis[V];
int vis[V];
int n;
void init(int n_)
{
n=n_;
for(int i=0;i<n;i++) g[i].clear();
}
void addedge(int u,int v,T w)
{
g[u].emplace_back(w,v);
if(!Directed) g[v].emplace_back(w,u);
}
void dijkstra(int st,int ed=-1) // ed=-1 no destination
{
for(int i=0;i<n;i++) dis[i]=INF,vis[i]=0;
priority_queue<PTI,vector<PTI>,greater<PTI> > qu;
dis[st]=ZERO;
qu.emplace(ZERO,st);
while(!qu.empty())
{
PTI p=qu.top(); qu.pop();
int u=p.second;
if(vis[u]) continue;
vis[u]=1;
if(u==ed) break;
for(auto [w,v]:g[u])
{
if(vis[v]) continue;
T nd=dis[u]+w;
if(nd<dis[v])
{
dis[v]=nd;
qu.emplace(nd,v);
}
}
}
}
};
Debug:
/* Debug ------------------------------------
T need to define function
ostream& operator<<(ostream& out, T rhs); */
void show()
{
cout<<"Dijkstra:----------------------\n";
cout<<"id:";
for(int i=0;i<n;i++) cout<<'\t'<<i;
cout<<'\n';
cout<<"dis:";
for(int i=0;i<n;i++) cout<<'\t'<<dis[i];
cout<<'\n';
cout<<"vis:";
for(int i=0;i<n;i++) cout<<'\t'<<vis[i];
cout<<'\n';
cout<<"-------------------------------\n\n";
}
模板 (Heap)
// must define < for T
// M: max size of heap
// MK: max size of key
template<typename T,size_t M>
struct Heap
{
typedef pair<T,int> PTI;
T h[M+1];
int key[M+1]; // key[i] is unique and in [0~M-1]
int pos[M]; // position of elememt which key is i
int n; // number of node in the current heap
void init() { n=0; }
void push(T x,int k)
{
h[++n]=x; key[n]=k; pos[k]=n; swim(n);
}
PTI pop()
{
T res=h[1]; int k=key[1];
h[1]=h[n]; key[1]=key[n--]; pos[key[1]]=1;
sink(1);
return {res,k};
}
// decrease key to val
void dec(int k,T val) // check key in [0~n-1]
{
int p=pos[k];
T oldval=h[p];
if(val<oldval) { h[p]=val; swim(p); }
}
bool empty() { return n==0; }
/* Helper ----------------------------------- */
void sink(int p)
{
int q=p<<1; T x=h[p]; int k=key[p];
while(q<=n)
{
if(q<n&&h[q+1]<h[q]) q++;
if(!(h[q]<x)) break; // h[q]>=x
h[p]=h[q]; key[p]=key[q]; pos[key[p]]=p;
p=q; q=p<<1;
}
h[p]=x; key[p]=k; pos[k]=p;
}
void swim(int p)
{
int q=p>>1; T x=h[p]; int k=key[p];
while(q&&x<h[q])
{
h[p]=h[q]; key[p]=key[q]; pos[key[p]]=p;
p=q; q=p>>1;
}
h[p]=x; key[p]=k; pos[k]=p;
}
};
// T must define <
// V: max number of vertex [0~V-1]
template<typename T,size_t V,bool Directed=true;
T INF=T(0x3f3f3f3f),T ZERO=T(0)>
struct Dijkstra {
typedef pair<T,int> PTI;
vector<PTI> g[V];
T dis[V];
int vis[V];
int n;
Heap<T,V> heap;
void init(int n_)
{
n=n_;
for(int i=0;i<n;i++) g[i].clear();
}
void addedge(int u,int v,T w)
{
g[u].emplace_back(w,v);
if(!Directed) g[v].emplace_back(w,u);
}
void solve(int st,int ed=-1) // ed=-1 no destination
{
for(int i=0;i<n;i++) dis[i]=INF,vis[i]=0;
heap.init();
dis[st]=ZERO;
heap.push(ZERO,st);
while(!heap.empty())
{
PTI p=heap.pop();
int u=p.second;
if(vis[u]==2) continue;
vis[u]=2;
if(u==ed) break;
for(auto [w,v]:g[u])
{
if(vis[v]==2) continue;
T nd=dis[u]+w;
if(nd<dis[v])
{
dis[v]=nd;
if(!vis[v]) heap.push(nd,v),vis[v]=1;
else heap.dec(v,nd);
}
}
}
}
};
Debug:
/* Debug ------------------------------------
T need to define friend function
ostream& operator<<(ostream& out, T rhs); */
void show()
{
cout<<"Dijkstra:----------------------\n";
cout<<"id:";
for(int i=0;i<n;i++) cout<<'\t'<<i;
cout<<'\n';
cout<<"dis:";
for(int i=0;i<n;i++) cout<<'\t'<<dis[i];
cout<<'\n';
cout<<"vis:";
for(int i=0;i<n;i++) cout<<'\t'<<vis[i];
cout<<'\n';
cout<<"-------------------------------\n\n";
}
测试
题目 | 方法 | 优化 | 时间(ms) |
---|---|---|---|
Luogu 4779【模板】单源最短路径(标准版) | Dijkstra priority_queue | 1940 | |
Luogu 4779 | Dijkstra priority_queue | O(2) | 655 |
Luogu 4779 | Dijkstra heap | 1040 | |
Luogu 4779 | Dijkstra heap | O(2) | 618 |
Next: [模板][数据结构] 并查集 Union Find / Disjoint Set Union