01BFS学习笔记

参考文章

基本思路

  • 使用deque,保证更优路径先被处理只记录最优信息 ,所以一旦 dist 更新就不再更新,不需要额外松弛。
    • 如果当前边权为 0,则将目标节点 加入队首;
    • 如果当前边权为 1,则将目标节点 加入队尾。
  • 注意当图的边权都是0/1的时候才能用

板子题

P4554

cpp 复制代码
const int N=500,inf=1e18,mod=998244353;
string a[N];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int dis[N][N];
void solve()
{
    int n,m;
    while(cin>>n>>m&&n&&m){
        forr(i,0,n-1){
            cin>>a[i];
        }
        forr(i,0,n-1)forr(j,0,m-1)dis[i][j]=inf;//要记录路径最小值 先初始化为最大值
        int x1,y1,x2,y2;cin>>x1>>y1>>x2>>y2;
        deque<pii>q;
        //原点入队
        q.push_back({x1,y1});dis[x1][y1]=0;
        
        int ans=1e18;
        while(q.size()){
            auto [x,y]=q.front();
            q.pop_front();
            char c=a[x][y];
            
            forr(i,0,3){//遍历下一步
                int nx=x+dx[i],ny=y+dy[i],ndis;//ndis记录走到(nx,ny)的代价,确定是最优才会放入dis数组和deque
                //判断边界
                if(nx>n-1||ny>m-1||nx<0||ny<0)continue;
                //计算代价
                if(c==a[nx][ny])ndis=dis[x][y];
                else ndis=dis[x][y]+1;
                //如果到了目的地 更新答案
                if(nx==x2&&ny==y2)ans=min(ndis,ans);
                //确认最优
                if(ndis<dis[nx][ny]){
                    dis[nx][ny]=ndis;
                    if(c==a[nx][ny])q.push_front({nx,ny});//本次不用消耗代价 贪心地认为是更优的 放到队首
                    else q.push_back({nx,ny});//本次消耗代价的放在队尾
                }
            }
        }
        cout<<ans<<endl;
    }
}

P1948 二分+01BFS

cpp 复制代码
const int N=1e3+10,M=6e3+10,mod=998244353,inf=1e18;
//"最少"成本 免费k个就选最长的k个 
//总费用决定于其中最长的电话线的长度 二分需要花钱的最大值
vector<pii>g[N];
int n,p,k;
int dis[N];
bool check(int x){
    // forr(i,1,n)forr(j,1,n)dis[i][j]=inf;
    forr(i,1,n)dis[i]=inf;
    deque<int>q;
    q.push_back(1);dis[1]=0;
    while(q.size()){
        int now=q.front();q.pop_front();
        for(auto [nxt,len]:g[now]){
            int nd;
            if(len<=x)nd=dis[now];
            else nd=dis[now]+1;

            if(nd<dis[nxt]){
                dis[nxt]=nd;
                if(len>x)q.push_back(nxt);
                else q.push_front(nxt);
            }
        }
    }
    return dis[n]<=k;
}
void solve(){
    cin>>n>>p>>k;
    forr(i,1,p){
        int a,b,l;cin>>a>>b>>l;
        g[a].push_back({b,l});
        g[b].push_back({a,l});
    }
    int l=0,r=1e7;//二分最长的付费长度
    int ans=-1;
    while(l<r){
        int mid=(l+r)>>1;
        if(check(mid))r=mid,ans=mid;
        else l=mid+1;
    }
    cout<<ans<<endl;
}
相关推荐
疯狂打码的少年10 分钟前
【计算机网络】TCP/IP协议族(四层体系结构,与OSI对比)
网络·笔记·tcp/ip·计算机网络
xqqxqxxq37 分钟前
AI Agent学习:Agent协作工具技术笔记(李博杰《深入理解 AI Agent》4.6观后总结)
笔记·学习
白猫不黑39 分钟前
大学网安方向学习路线:零基础与有基础的学习顺序整理
学习·web安全·计算机·网络安全·信息安全·编程·src漏洞
2601_965742221 小时前
全媒体运营与短视频代运营,两者有什么区别?
大数据·数据结构·人工智能·算法·ai·媒体
工业HMI实战笔记2 小时前
玩具制造HMI:注塑成型的快速换模与质量监控界面
人工智能·学习·交互·制造
wordbaby2 小时前
混合检索:两全其美的艺术
人工智能·算法
你在我身后2 小时前
发展路线建议
学习
彧azz2 小时前
数据结构:关于图的学习
c语言·数据结构·笔记·学习·算法
热心网友俣先生2 小时前
A题-药材的烘干问题-题意逐句翻译
算法·数学建模
苦猿的大模型日记2 小时前
Day57|从0学习 Claude Code(七):我没把说明书全塞给它,用到哪本才翻哪本
学习