欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

UVA1599-字典序+BFS

程序员文章站 2022-06-03 18:37:10
...

第一次写这么复杂的bfs,卡了我近一周,需要注意的细节很多,很多地方感觉跟题解差不多,但是就是不对。失之毫厘谬以千里啊。

这里是原题
这里是我当时看的一个比较好的题解(里面用的指针我不懂 但思路非常棒)

大概做法

先从n开始bfs,得到每个点到n的最短距离d[i]。然后从起点开始bfs,每一步保证d[v]=d[u]-1,同时储存最小字典序

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#define maxn 100005
using namespace std;
typedef struct edge{
    int col,to;
    edge(int a,int b):to(a),col(b){}

}Edge;
vector <Edge>e[maxn];  //邻接表储存图
int n,m,u,v,c,d[maxn],ans[maxn*4];//uvc是临时变量 个人习惯
bool vis[maxn];
void init()
{
    memset(ans,0x3f,sizeof ans);
    memset(d,-1,sizeof d); 
    memset(vis,0,sizeof vis);
    for (int i=1;i<=n;i++)e[i].clear(); 

    for(int i=1;i<=m;++i){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        if(a==b)continue;
        e[a].push_back(edge(b,c));
        e[b].push_back(edge(a,c));  //双向边   
    } 

    return ;

}
void fbfs(){

    queue<int >q;
    q.push(n);
    d[n]=0;
    while(!q.empty()){
        u=q.front();
        q.pop();
    //  if(u==1){return ;}这里建议大家把图遍历全,不要贪图那一点点时间,不然会出现玄学bug

        for(int i=0,len=e[u].size();i<len;++i){
            v=e[u][i].to;
            if(d[v]!=-1)continue;//不重复访问 写过复杂图bfs的应该都懂
            d[v]=d[u]+1;
            q.push(v);
        }
    }
    return ;
}
void bfs(){
/*
这个题有一点很重要,需要先在这里说明,一不能简单更新ans(见图2),二每个点会入队多遍但只会访问一遍(见题中样例,如果每个点只入队一遍就会错过后来的更优解)
这些在我下面的代码里都有所体现
*/
    queue<pair<int,int> >q;  //这里很秒 first 储存节点编号,second储存访问到达这个节点的边的颜色  我也是看别人代码学会的
    q.push(make_pair(1,0));
    ans[0]=0;//
    while(!q.empty()){
        u=q.front().first;
        c=q.front().second;

        q.pop();
        if(ans[d[1]-d[u]]!=c||u==n||vis[u])continue;
        //一满足沿着最短路线走 二别走过  三只访问一遍即可
        vis[u]=1;


        for(int i=0,len=e[u].size();i<len;++i){

            v=e[u][i].to;
            c=e[u][i].col;
            if(d[u]!=d[v]+1||c>=ans[d[1]-d[v]])continue;
            ans[d[1]-d[v]]=c;//更新第(d[1]-d[v])步最小颜色
        }

        for(int i=0,len=e[u].size();i<len;++i){
            v=e[u][i].to;
            c=e[u][i].col;
            if(d[u]!=d[v]+1||c!=ans[d[1]-d[v]])continue;  //如果有多个当前最优解 把他们全部入队
            q.push(make_pair(v,c));

        }
        //有可能当前阶段有多个解能到达点i,但到达点i的路径颜色不同或相同,这时就会通过开头的剪枝,将他们去掉  因为将该层遍历完后一定能得到最优解的颜色   就可以通过比较ans[]只访问最优解, 并通过vis只访问一次最优解


    }


}
int main(){

    while(scanf("%d%d",&n,&m)==2){

    init();

    fbfs();//从n开始

    bfs();//从1开始

    printf("%d\n", d[1]);  
        for (int i = 1; i<=d[1]; i++)  
            printf("%d%c",ans[i],i==d[1]?'\n':' ');

    }
    return 0;
}

UVA1599-字典序+BFS