054.Dijkstra模板+反向索引堆优化 + 经典题目
Dijkstra
-
BFS+ 贪心(priority_queue) -
加权有向图
-
不能处理负权
Dij(普通堆)
O ( M * logM )
M : 边数
const int N=1e5+5;
const int INF=0x3f3f3f3f;
vector<pair<int,int>>gra[N];
bool vis[N];
int dis[N];
void built(int siz){
for(int i=1;i<=siz;++i){
gra[i].clear();
vis[i]=0;
dis[i]=INF;
}
}
void Dijkstra(int s){
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<>>pq;
dis[s]=0;
pq.push({0,s});
while(pq.size()){
auto [d,u]=pq.top();
pq.pop();
if(vis[u]==0){
vis[u]=1;
for(auto [w,v]:gra[u]){
if(vis[v]==0&&dis[v]>d+w){
dis[v]=d+w
pq.push({dis[v],v});
}
}
}
}
}
Dij(反向索引堆)
O ( M * logN )
M : 边数
N : 节点数
const int N=1e5+5;
const int M=2e5+5;
const int INF=0x3f3f3f3f;
int dis[N];
int tot;
int head[N];
int nex[M];
int to[M];
int val[M];
int heap[N];
int tag[N];
int siz;
void built(int n){
tot=1;
siz=0;
for(int i=1;i<=n;++i){
dis[i]=INF;
head[i]=0;
tag[i]=-1;
}
}
void addEdge(int u,int v,int w){
nex[tot]=head[u];
to[tot]=v;
val[tot]=w;
head[u]=tot++;
}
void swap(int i,int j){
int t=heap[i];
heap[i]=heap[j];
heap[j]=t;
tag[heap[i]]=i;
tag[heap[j]]=j;
}
void up(int i){
while(dis[heap[(i-1)/2]]>dis[heap[i]]){
swap(i,(i-1)/2);
i=(i-1)/2;
}
}
void down(int i){
int l=i*2+1;
while(l<siz){
int best=l+1<siz&&dis[heap[l+1]]<dis[heap[l]]?l+1:l;
if(dis[heap[i]]<=dis[heap[best]])return;
swap(best,i);
i=best;
l=2*i+1;
}
}
int pop(){
int u=heap[0];
swap(0,--siz);
down(0);
tag[u]=-2;
return u;
}
void push(int v,int c){
if(tag[v]==-2)return;
if(tag[v]==-1){
heap[siz]=v;
tag[v]=siz++;
dis[v]=c;
}
else dis[v]=min(dis[v],c);
up(tag[v]);
}
void Dijkstra(int s){
push(s,0);
while(siz){
int u=pop();
for(int ei=head[u];ei;ei=nex[ei]){
push(to[ei],dis[u]+val[ei]);
}
}
}
习题
这里我的写法都是普通堆
01 模板
02 网路延迟时间
code
class Solution {
struct e{int to,cost;};
public:
int networkDelayTime(vector<vector<int>>& times, int n, int k) {
vector<vector<e>>gra(n+1);
for(auto edge:times){
gra[edge[0]].push_back({edge[1],edge[2]});
}
auto cmp=[&](e a,e b){return a.cost>b.cost;};
priority_queue<e,vector<e>,decltype(cmp)>pq(cmp);
vector<int>dis(n+1,0x3f3f3f3f);
vector<int>vis(n+1,0);
dis[k]=0;
pq.push({k,0});
while(pq.size()){
auto [cur,d]=pq.top();
pq.pop();
if(vis[cur]==0){
vis[cur]=1;
for(auto [v,w]:gra[cur]){
if(vis[v]==0){
int cost=w+d;
if(cost<dis[v]){
dis[v]=cost;
pq.push({v,cost});
}
}
}
}
}
int ans=-1;
for(int i=1;i<=n;++i){
ans=max(ans,dis[i]);
}
return ans==0x3f3f3f3f?-1:ans;
}
};
03 最优乘车
code
const int N=510;
const int INF=0x3f3f3f3f;
int dis[N];
bool vis[N];
vector<pair<int,int>>gra[N];
int Dijkstra(int s,int e,int n){
for(int i=1;i<=n;++i){
dis[i]=INF;
vis[i]=0;
}
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<>>pq;
pq.push({0,s});
dis[s]=0;
while(pq.size()){
auto [d,u]=pq.top();
pq.pop();
if(vis[u]==0){
vis[u]=1;
for(auto [w,v]:gra[u]){
if(vis[v]==0&&dis[v]>d+w){
dis[v]=w+d;
pq.push({dis[v],v});
}
}
}
}
return dis[e];
}
void solve(){
int m,n;
cin>>m>>n;
cin.ignore();
cin.ignore();
for(int i=1;i<=n;++i){
gra[i].clear();
}
for(int i=0;i<m;++i){
string str;
getline(cin,str);
stringstream ss(str);
vector<int>t;
int node;
while(ss>>node){
t.push_back(node);
}
for(int i=0;i<t.size();++i){
for(int j=i+1;j<t.size();++j){
gra[t[i]].push_back({1,t[j]});
}
}
}
int ans=Dijkstra(1,n,n);
if(ans==INF)cout<<"NO";
else if(ans==0)cout<<0;
else cout<<ans-1;
}
04 最小瓶颈
code
class Solution {
struct e{int x,y,d;};
vector<int>mo{-1,0,1,0,-1};
public:
int minimumEffortPath(vector<vector<int>>& g) {
int n=g.size();
int m=g[0].size();
vector<vector<int>>dis(n,vector<int>(m,0x3f3f3f3f));
vector<vector<int>>vis(n,vector<int>(m,0));
auto cmp=[&](e a,e b){return a.d>b.d;};
priority_queue<e,vector<e>,decltype(cmp)>pq(cmp);
pq.push({0,0,0});
while(pq.size()){
auto [x,y,c]=pq.top();
pq.pop();
if(vis[x][y]==0){
if(x==n-1&&y==m-1)return c;
vis[x][y]=1;
for(int i=0;i<4;++i){
int nx=x+mo[i];
int ny=y+mo[i+1];
if(nx>=0&&ny>=0&&nx<n&&ny<m&&vis[nx][ny]==0){
int nc=max(c,abs(g[x][y]-g[nx][ny]));
if(nc<dis[nx][ny]){
dis[nx][ny]=nc;
pq.push({nx,ny,nc});
}
}
}
}
}
return -1;
}
};
05 水位上升游泳
code
class Solution {
struct e{int x,y,d;};
vector<int>mo{-1,0,1,0,-1};
public:
int swimInWater(vector<vector<int>>& g) {
int n=g.size();
int m=g[0].size();
vector<vector<int>>dis(n,vector<int>(m,0x3f3f3f3f));
vector<vector<int>>vis(n,vector<int>(m,0));
auto cmp=[&](e a,e b){return a.d>b.d;};
priority_queue<e,vector<e>,decltype(cmp)>pq(cmp);
pq.push({0,0,g[0][0]});
while(pq.size()){
auto [x,y,c]=pq.top();
pq.pop();
if(vis[x][y]==0){
if(x==n-1&&y==m-1)return c;
vis[x][y]=1;
for(int i=0;i<4;++i){
int nx=x+mo[i];
int ny=y+mo[i+1];
if(nx>=0&&ny>=0&&nx<n&&ny<m&&vis[nx][ny]==0){
int nc=max(c,g[nx][ny]);
if(nc<dis[nx][ny]){
dis[nx][ny]=nc;
pq.push({nx,ny,nc});
}
}
}
}
}
return -1;
}
};
06 概率最大的路径
code
class Solution {
struct st{
int u;
double d;
};
public:
double maxProbability(int n, vector<vector<int>>& edges, vector<double>& suc, int s, int e) {
vector<vector<st>>gra(n);
for(int i=0;i<(int)suc.size();++i){
gra[edges[i][0]].push_back({edges[i][1],suc[i]});
gra[edges[i][1]].push_back({edges[i][0],suc[i]});
}
vector<double>dis(n,0);
vector<bool>vis(n,0);
auto cmp=[](st a,st b){return a.d<b.d;};
priority_queue<st,vector<st>,decltype(cmp)>pq(cmp);
pq.push({s,1});
dis[s]=1;
while(pq.size()){
auto [u,d]=pq.top();
pq.pop();
if(u==e){
return d;
}
if(vis[u]==0){
vis[u]=1;
for(auto [v,w]:gra[u]){
double nd=d*w;
if(nd>dis[v]){
dis[v]=nd;
pq.push({v,nd});
}
}
}
}
return 0;
}
};
07 使网格图至少有一条有效路径的最小代价
code
class Solution {
vector<int>mo{-1,0,1,0,-1};
struct st{
int x;
int y;
int c;
};
public:
int minCost(vector<vector<int>>& g) {
int n=g.size();
int m=g[0].size();
vector<vector<int>>dis(n,vector<int>(m,0x3f3f3f3f));
vector<vector<bool>>vis(n,vector<bool>(m,0));
auto cmp=[](st a,st b){return a.c>b.c;};
priority_queue<st,vector<st>,decltype(cmp)>pq(cmp);
pq.push({0,0,0});
dis[0][0]=0;
while(pq.size()){
auto [x,y,c]=pq.top();
pq.pop();
if(x==n-1&&y==m-1)return c;
if(vis[x][y]==0){
vis[x][y]=1;
int xx=x,yy=y;
if(g[x][y]==1)yy++;
if(g[x][y]==2)yy--;
if(g[x][y]==3)xx++;
if(g[x][y]==4)xx--;
for(int i=0;i<4;++i){
int nx=x+mo[i];
int ny=y+mo[i+1];
if(nx<0||ny<0||nx>=n||ny>=m)continue;
int nc=c+1;
if(xx==nx&&yy==ny)nc--;
if(dis[nx][ny]>nc){
dis[nx][ny]=nc;
pq.push({nx,ny,nc});
}
}
}
}
return -1;
}
};
I am the bone of my sword

浙公网安备 33010602011771号