HELLO WO|

kingwzun

园龄:3年6个月粉丝:111关注:0

2022-08-08 20:59阅读: 308评论: 0推荐: 0

双端队列_01bfs _ 最短路

概述

作用:
求图中只有两种权值边的最短路

理解:
如果我们的图中只有两种边0或者1(1也可以是任意的正数)。
每次从队头取出元素,我们就可以使用一个双端队列来模拟dij中的优先队列:

  • 如果扩展到的边权值为0,就放入队头。
  • 如果扩展到的边权值为1,就放入队尾。

很显然这样是满足优先队列的。因此算法是正确的。

模板代码

写法和dij的一样

vector<pii> g[N];
int dist[N];
bool vis[N];
void bfs(int be,int en){
dist[be]=0;
deque<int> q;
q.push_back(be);
while(q.size()){
int k=q.front();
q.pop_front();
if(vis[k]) continue;
vis[k]=true;
for(pii t: g[k]){
int ver=t.first,dis=t.second;
int cnt=dist[k]+dis;
if(dist[ver]>cnt){
dist[ver]=cnt;
if(dis) q.push_back(ver);
else q.push_front(ver);
}
}
}
cout<<dist[en]<<endl;
}

应用

P4554 小明的游戏 模板题

175. 电路维修

代码:

#include <bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
// #define int long long
const int N = 510,M=N*N;
int n,m;
char g[N][N];
int dist[N][N];
bool st[N][N];
int dx[]={-1,-1,1,1},dy[]={-1,1,1,-1};//相邻点
int ix[]={-1,-1,0,0},iy[]={-1,0,0,-1};//相邻边
int bfs(){
memset(dist,0x3f,sizeof dist);
memset(st,0,sizeof st);
//四个方向正确的方向 (\\就是\ 因为是转义字符所以写两个)
char cs[]="\\/\\/";
dist[0][0]=0;
deque<pii> q;
q.push_back({0,0});
while(q.size()){
pii k=q.front();
q.pop_front();
int x=k.first,y=k.second;
if(st[x][y]) continue;
st[x][y]=true;
for(int i=0;i<4;i++){
int a=x+dx[i],b=y+dy[i];
if(a<0 || a>n || b<0 || b>m) continue;
//更新路径,求长度
int ca=x+ix[i],cb=y+iy[i];
int d=dist[x][y]+(g[ca][cb]!=cs[i]);
if(dist[a][b]>d){
dist[a][b]=d;
if(g[ca][cb]!=cs[i]) q.push_back({a,b});
else q.push_front({a,b});
}
}
}
return dist[n][m];
}
void solve()
{
cin>>n>>m;
for(int i=0;i<n;i++) cin>>g[i];
int t=bfs();
if(t==0x3f3f3f3f) puts("NO SOLUTION");
else cout<<t<<endl;
}
signed main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
int t = 1;
cin>>t;
while (t--)
solve();
return 0;
}

本文作者:kingwzun

本文链接:https://www.cnblogs.com/kingwz/p/16532689.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   kingwzun  阅读(308)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起